]> git.proxmox.com Git - mirror_edk2.git/blob - IntelFrameworkModulePkg/Universal/SetupBrowserDxe/Boolean.c
Rename Protocol/FormCallback.h to Protocol/FormCallbackFramework.h to follow the...
[mirror_edk2.git] / IntelFrameworkModulePkg / Universal / SetupBrowserDxe / Boolean.c
1 /*++
2
3 Copyright (c) 2006 - 2007, Intel Corporation
4 All rights reserved. This program and the accompanying materials
5 are licensed and made available under the terms and conditions of the BSD License
6 which accompanies this distribution. The full text of the license may be found at
7 http://opensource.org/licenses/bsd-license.php
8
9 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
10 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
11
12 Module Name:
13
14 Boolean.c
15
16 Abstract:
17
18 This routine will evaluate the IFR inconsistency data to determine if
19 something is a valid entry for a particular expression
20
21 --*/
22
23 //
24 // Include common header file for this module.
25 //
26 #include "CommonHeader.h"
27
28 #include "Setup.h"
29 #include "Ui.h"
30
31 //
32 // Global stack used to evaluate boolean expresions
33 //
34 BOOLEAN *mBooleanEvaluationStack = (BOOLEAN) 0;
35 BOOLEAN *mBooleanEvaluationStackEnd = (BOOLEAN) 0;
36
37 STATIC
38 VOID
39 GrowBooleanStack (
40 IN OUT BOOLEAN **Stack,
41 IN UINTN StackSizeInBoolean
42 )
43 /*++
44
45 Routine Description:
46
47 Grow size of the boolean stack
48
49 Arguments:
50
51 Stack - Old stack on the way in and new stack on the way out
52
53 StackSizeInBoolean - New size of the stack
54
55 Returns:
56
57 NONE
58
59 --*/
60 {
61 BOOLEAN *NewStack;
62
63 NewStack = AllocatePool (StackSizeInBoolean * sizeof (BOOLEAN));
64 ASSERT (NewStack != NULL);
65
66 if (*Stack != NULL) {
67 //
68 // Copy to Old Stack to the New Stack
69 //
70 CopyMem (
71 NewStack,
72 mBooleanEvaluationStack,
73 (mBooleanEvaluationStackEnd - mBooleanEvaluationStack) * sizeof (BOOLEAN)
74 );
75
76 //
77 // Make the Stack pointer point to the old data in the new stack
78 //
79 *Stack = NewStack + (*Stack - mBooleanEvaluationStack);
80
81 //
82 // Free The Old Stack
83 //
84 FreePool (mBooleanEvaluationStack);
85 }
86
87 mBooleanEvaluationStack = NewStack;
88 mBooleanEvaluationStackEnd = NewStack + StackSizeInBoolean;
89 }
90
91 STATIC
92 VOID
93 InitializeBooleanEvaluator (
94 VOID
95 )
96 /*++
97
98 Routine Description:
99
100 Allocate a global stack for boolean processing.
101
102 Arguments:
103
104 NONE
105
106 Returns:
107
108 NONE
109
110 --*/
111 {
112 BOOLEAN *NullStack;
113
114 NullStack = NULL;
115 GrowBooleanStack (&NullStack, 0x1000);
116 }
117
118 STATIC
119 VOID
120 PushBool (
121 IN OUT BOOLEAN **Stack,
122 IN BOOLEAN BoolResult
123 )
124 /*++
125
126 Routine Description:
127
128 Push an element onto the Boolean Stack
129
130 Arguments:
131
132 Stack - Current stack location.
133 BoolResult - BOOLEAN to push.
134
135 Returns:
136
137 None.
138
139 --*/
140 {
141 CopyMem (*Stack, &BoolResult, sizeof (BOOLEAN));
142 *Stack += 1;
143
144 if (*Stack >= mBooleanEvaluationStackEnd) {
145 //
146 // If we run out of stack space make a new one that is 2X as big. Copy
147 // the old data into the new stack and update Stack to point to the old
148 // data in the new stack.
149 //
150 GrowBooleanStack (
151 Stack,
152 (mBooleanEvaluationStackEnd - mBooleanEvaluationStack) * sizeof (BOOLEAN) * 2
153 );
154 }
155 }
156
157 STATIC
158 BOOLEAN
159 PopBool (
160 IN OUT BOOLEAN **Stack
161 )
162 /*++
163
164 Routine Description:
165
166 Pop an element from the Boolean stack.
167
168 Arguments:
169
170 Stack - Current stack location
171
172 Returns:
173
174 Top of the BOOLEAN stack.
175
176 --*/
177 {
178 BOOLEAN ReturnValue;
179
180 *Stack -= 1;
181 CopyMem (&ReturnValue, *Stack, sizeof (BOOLEAN));
182 return ReturnValue;
183 }
184
185 STATIC
186 EFI_STATUS
187 GrowBooleanExpression (
188 IN EFI_INCONSISTENCY_DATA *InconsistentTags,
189 OUT VOID **BooleanExpression,
190 IN OUT UINTN *BooleanExpressionLength
191 )
192 {
193 UINT8 *NewExpression;
194
195 NewExpression = AllocatePool (*BooleanExpressionLength + sizeof (EFI_INCONSISTENCY_DATA));
196 ASSERT (NewExpression != NULL);
197
198 if (*BooleanExpression != NULL) {
199 //
200 // Copy Old buffer to the New buffer
201 //
202 CopyMem (NewExpression, *BooleanExpression, *BooleanExpressionLength);
203
204 CopyMem (&NewExpression[*BooleanExpressionLength], InconsistentTags, sizeof (EFI_INCONSISTENCY_DATA));
205
206 //
207 // Free The Old buffer
208 //
209 FreePool (*BooleanExpression);
210 } else {
211 //
212 // Copy data into new buffer
213 //
214 CopyMem (NewExpression, InconsistentTags, sizeof (EFI_INCONSISTENCY_DATA));
215 }
216
217 *BooleanExpressionLength = *BooleanExpressionLength + sizeof (EFI_INCONSISTENCY_DATA);
218 *BooleanExpression = (VOID *) NewExpression;
219 return EFI_SUCCESS;
220 }
221
222 STATIC
223 VOID
224 CreateBooleanExpression (
225 IN EFI_FILE_FORM_TAGS *FileFormTags,
226 IN UINT16 Value,
227 IN UINT16 Id,
228 IN BOOLEAN Complex,
229 OUT VOID **BooleanExpression,
230 OUT UINTN *BooleanExpressionLength
231 )
232 /*++
233
234 Routine Description:
235
236 Arguments:
237
238 Returns:
239
240 --*/
241 {
242 UINTN Count;
243 EFI_INCONSISTENCY_DATA *InconsistentTags;
244 EFI_INCONSISTENCY_DATA FakeInconsistentTags;
245
246 InconsistentTags = FileFormTags->InconsistentTags;
247
248 //
249 // Did we run into a question that contains the Id we are looking for?
250 //
251 for (Count = 0; InconsistentTags->Operand != 0xFF; Count++) {
252
253 //
254 // Reserve INVALID_OFFSET_VALUE - 1 for TURE and FALSE, because we need to treat them as well
255 // as ideqid etc. but they have no coresponding id, so we reserve this value.
256 //
257 if (InconsistentTags->QuestionId1 == Id ||
258 InconsistentTags->QuestionId1 == INVALID_OFFSET_VALUE - 1) {
259 //
260 // If !Complex - means evaluate a single if/endif expression
261 //
262 if (!Complex) {
263 //
264 // If the ConsistencyId does not match the expression we are looking for
265 // skip to the next consistency database entry
266 //
267 if (InconsistentTags->ConsistencyId != Value) {
268 goto NextEntry;
269 }
270 }
271 //
272 // We need to rewind to the beginning of the Inconsistent expression
273 //
274 for (;
275 (InconsistentTags->Operand != EFI_IFR_INCONSISTENT_IF_OP) &&
276 (InconsistentTags->Operand != EFI_IFR_GRAYOUT_IF_OP) &&
277 (InconsistentTags->Operand != EFI_IFR_SUPPRESS_IF_OP);
278 ) {
279 InconsistentTags = InconsistentTags->Previous;
280 }
281 //
282 // Store the consistency check expression, ensure the next for loop starts at the op-code afterwards
283 //
284 GrowBooleanExpression (InconsistentTags, BooleanExpression, BooleanExpressionLength);
285 InconsistentTags = InconsistentTags->Next;
286
287 //
288 // Keep growing until we hit the End expression op-code or we hit the beginning of another
289 // consistency check like grayout/suppress
290 //
291 for (;
292 InconsistentTags->Operand != EFI_IFR_END_IF_OP &&
293 InconsistentTags->Operand != EFI_IFR_GRAYOUT_IF_OP &&
294 InconsistentTags->Operand != EFI_IFR_SUPPRESS_IF_OP;
295 ) {
296 GrowBooleanExpression (InconsistentTags, BooleanExpression, BooleanExpressionLength);
297 InconsistentTags = InconsistentTags->Next;
298 }
299 //
300 // Store the EndExpression Op-code
301 //
302 GrowBooleanExpression (InconsistentTags, BooleanExpression, BooleanExpressionLength);
303 }
304
305 NextEntry:
306 if (InconsistentTags->Next != NULL) {
307 //
308 // Skip to next entry
309 //
310 InconsistentTags = InconsistentTags->Next;
311 }
312 }
313
314 FakeInconsistentTags.Operand = 0;
315
316 //
317 // Add one last expression which will signify we have definitely hit the end
318 //
319 GrowBooleanExpression (&FakeInconsistentTags, BooleanExpression, BooleanExpressionLength);
320 }
321
322 STATIC
323 EFI_STATUS
324 BooleanVariableWorker (
325 IN CHAR16 *VariableName,
326 IN EFI_VARIABLE_DEFINITION *VariableDefinition,
327 IN BOOLEAN *StackPtr,
328 IN OUT UINTN *SizeOfVariable,
329 IN OUT VOID **VariableData
330 )
331 /*++
332
333 Routine Description:
334
335
336 Arguments:
337
338 Returns:
339
340 --*/
341 {
342 EFI_STATUS Status;
343
344 Status = gRT->GetVariable (
345 VariableName,
346 &VariableDefinition->Guid,
347 NULL,
348 SizeOfVariable,
349 *VariableData
350 );
351
352 if (EFI_ERROR (Status)) {
353
354 if (Status == EFI_BUFFER_TOO_SMALL) {
355 *VariableData = AllocatePool (*SizeOfVariable);
356 ASSERT (*VariableData != NULL);
357
358 Status = gRT->GetVariable (
359 VariableName,
360 &VariableDefinition->Guid,
361 NULL,
362 SizeOfVariable,
363 *VariableData
364 );
365 }
366
367 if (Status == EFI_NOT_FOUND) {
368 //
369 // This is a serious flaw, we must have some standard result if a variable
370 // is not found. Our default behavior must either be return a TRUE or FALSE
371 // since there is nothing else we can really do. Therefore, my crystal ball
372 // says I will return a FALSE
373 //
374 PushBool (&StackPtr, FALSE);
375 }
376 }
377
378 return Status;
379 }
380
381 STATIC
382 UINT8
383 PredicateIfrType (
384 IN EFI_INCONSISTENCY_DATA *Iterator
385 )
386 /*++
387
388 Routine Description:
389 This routine is for the purpose of predicate whether the Ifr is generated by a VfrCompiler greater than or equal to 1.88 or
390 less than 1.88 which is legacy.
391
392 Arguments:
393 Iterator - The pointer to inconsistency tags
394
395 Returns:
396
397 0x2 - If IFR is not legacy
398
399 0x1 - If IFR is legacy
400
401 --*/
402 {
403 //
404 // legacy Ifr cover the states:
405 // Not ...
406 // Operand Opcode Operand
407 //
408 // while Operand means ideqval, TRUE, or other what can be evaluated to True or False,
409 // and Opcode means AND or OR.
410 //
411 if (Iterator->Operand == EFI_IFR_NOT_OP ||
412 Iterator->Operand == 0) {
413 return 0x1;
414 } else if (Iterator->Operand == EFI_IFR_EQ_VAR_VAL_OP ||
415 Iterator->Operand == EFI_IFR_EQ_ID_VAL_OP ||
416 Iterator->Operand == EFI_IFR_EQ_ID_ID_OP ||
417 Iterator->Operand == EFI_IFR_EQ_ID_LIST_OP) {
418 Iterator++;
419 if (Iterator->Operand == EFI_IFR_AND_OP ||
420 Iterator->Operand == EFI_IFR_OR_OP) {
421 Iterator--;
422 return 0x1;
423 }
424 Iterator--;
425 }
426 return 0x2;
427 }
428
429 STATIC
430 VOID
431 PostOrderEvaluate (
432 IN EFI_FILE_FORM_TAGS *FileFormTags,
433 IN UINT16 Width,
434 IN OUT EFI_INCONSISTENCY_DATA **PIterator,
435 IN OUT BOOLEAN **StackPtr
436 )
437 /*++
438
439 Routine Description:
440 PostOrderEvaluate is used for Ifr generated by VfrCompiler greater than or equal to 1.88,
441 which generate Operand Operand Opcode type Ifr.
442 PostOrderEvaluete only evaluate boolean expression part, not suppressif/grayoutif. TRUE,
443 FALSE, >=, >, (, ) are supported.
444
445 Arguments:
446
447 FileFormTags - The pointer to the tags of the form
448
449 Width - Width of Operand, recognized every iteration
450
451 PIterator - The pointer to inconsistency tags
452
453 StackPtr - The pointer to the evaluation stack
454
455 Returns:
456
457 TRUE - If value is valid
458
459 FALSE - If value is not valid
460
461 --*/
462 {
463 BOOLEAN Operator;
464 BOOLEAN Operator2;
465 UINT16 *MapBuffer;
466 UINT16 *MapBuffer2;
467 UINT16 MapValue;
468 UINT16 MapValue2;
469 UINTN SizeOfVariable;
470 CHAR16 VariableName[MAXIMUM_VALUE_CHARACTERS];
471 VOID *VariableData;
472 EFI_VARIABLE_DEFINITION *VariableDefinition;
473 EFI_STATUS Status;
474 UINTN Index;
475 BOOLEAN PushValue;
476
477 Operator = FALSE;
478 Operator2 = FALSE;
479 MapBuffer = NULL;
480 MapBuffer2 = NULL;
481 MapValue = 0;
482 MapValue2 = 0;
483 VariableData = NULL;
484
485 while (TRUE) {
486 if ((*PIterator)->Operand == 0) {
487 return;
488 }
489
490 Width = (*PIterator)->Width;
491
492 //
493 // Because INVALID_OFFSET_VALUE - 1 is reserved for TRUE or FALSE, omit them.
494 //
495 if ((*PIterator)->QuestionId1 != INVALID_OFFSET_VALUE &&
496 (*PIterator)->QuestionId1 != INVALID_OFFSET_VALUE - 1) {
497 ExtractNvValue (FileFormTags, (*PIterator)->VariableNumber, Width, (*PIterator)->QuestionId1, (VOID **) &MapBuffer);
498 ExtractNvValue (FileFormTags, (*PIterator)->VariableNumber2, Width, (*PIterator)->QuestionId2, (VOID **) &MapBuffer2);
499 if (MapBuffer != NULL) {
500 if (Width == 2) {
501 MapValue = *MapBuffer;
502 } else {
503 MapValue = (UINT8) *MapBuffer;
504 }
505
506 FreePool (MapBuffer);
507 }
508
509 if (MapBuffer2 != NULL) {
510 if (Width == 2) {
511 MapValue2 = *MapBuffer2;
512 } else {
513 MapValue2 = (UINT8) *MapBuffer2;
514 }
515
516 FreePool (MapBuffer2);
517 }
518 }
519
520 switch ((*PIterator)->Operand) {
521 case EFI_IFR_EQ_VAR_VAL_OP:
522 UnicodeValueToString (
523 VariableName,
524 FALSE,
525 (UINTN) (*PIterator)->QuestionId1,
526 (sizeof (VariableName) / sizeof (VariableName[0])) - 1
527 );
528
529 SizeOfVariable = 0;
530
531 ExtractRequestedNvMap (FileFormTags, (*PIterator)->VariableNumber, &VariableDefinition);
532
533 Status = BooleanVariableWorker (
534 VariableName,
535 VariableDefinition,
536 *StackPtr,
537 &SizeOfVariable,
538 &VariableData
539 );
540
541 if (!EFI_ERROR (Status)) {
542 if (SizeOfVariable == 1) {
543 CopyMem (&MapValue, VariableData, 1);
544 } else {
545 CopyMem (&MapValue, VariableData, 2);
546 }
547
548 //
549 // Do operation after knowing the compare operator.
550 //
551 MapValue2 = (*PIterator)->Value;
552 (*PIterator)++;
553 if ((*PIterator)->Operand == EFI_IFR_GT_OP) {
554 PushValue = (BOOLEAN) (MapValue > MapValue2);
555 } else if ((*PIterator)->Operand == EFI_IFR_GE_OP) {
556 PushValue = (BOOLEAN) (MapValue >= MapValue2);
557 } else {
558 (*PIterator)--;
559 PushValue = (BOOLEAN) (MapValue == MapValue2);
560 }
561 PushBool (StackPtr, PushValue);
562 }
563
564 break;
565
566 case EFI_IFR_EQ_ID_VAL_OP:
567 //
568 // Do operation after knowing the compare operator.
569 //
570 MapValue2 = (*PIterator)->Value;
571 (*PIterator)++;
572 if ((*PIterator)->Operand == EFI_IFR_GT_OP) {
573 PushValue = (BOOLEAN) (MapValue > MapValue2);
574 } else if ((*PIterator)->Operand == EFI_IFR_GE_OP) {
575 PushValue = (BOOLEAN) (MapValue >= MapValue2);
576 } else {
577 (*PIterator)--;
578 PushValue = (BOOLEAN) (MapValue == MapValue2);
579 }
580 PushBool (StackPtr, PushValue);
581 break;
582
583 case EFI_IFR_EQ_ID_ID_OP:
584 //
585 // Do operation after knowing the compare operator.
586 //
587 (*PIterator)++;
588 if ((*PIterator)->Operand == EFI_IFR_GT_OP) {
589 PushValue = (BOOLEAN) (MapValue > MapValue2);
590 } else if ((*PIterator)->Operand == EFI_IFR_GE_OP) {
591 PushValue = (BOOLEAN) (MapValue >= MapValue2);
592 } else {
593 (*PIterator)--;
594 PushValue = (BOOLEAN) (MapValue == MapValue2);
595 }
596 PushBool (StackPtr, PushValue);
597 break;
598
599 case EFI_IFR_EQ_ID_LIST_OP:
600 for (Index = 0; Index < (*PIterator)->ListLength; Index++) {
601 Operator = (BOOLEAN) (MapValue == (*PIterator)->ValueList[Index]);
602 if (Operator) {
603 break;
604 }
605 }
606
607 PushBool (StackPtr, Operator);
608 break;
609
610 case EFI_IFR_TRUE_OP:
611 PushBool (StackPtr, TRUE);
612 break;
613
614 case EFI_IFR_FALSE_OP:
615 PushBool (StackPtr, FALSE);
616 break;
617
618 case EFI_IFR_AND_OP:
619 Operator = PopBool (StackPtr);
620 Operator2 = PopBool (StackPtr);
621 PushBool (StackPtr, (BOOLEAN) (Operator && Operator2));
622 break;
623 case EFI_IFR_OR_OP:
624 Operator = PopBool (StackPtr);
625 Operator2 = PopBool (StackPtr);
626 PushBool (StackPtr, (BOOLEAN) (Operator || Operator2));
627 break;
628 case EFI_IFR_NOT_OP:
629 Operator = PopBool (StackPtr);
630 PushBool (StackPtr, (BOOLEAN) (!Operator));
631 break;
632
633 case EFI_IFR_SUPPRESS_IF_OP:
634 case EFI_IFR_GRAYOUT_IF_OP:
635 case EFI_IFR_INCONSISTENT_IF_OP:
636 default:
637 //
638 // Return to the previous tag if runs out of boolean expression.
639 //
640 (*PIterator)--;
641 return;
642 }
643 (*PIterator)++;
644 }
645 }
646
647 BOOLEAN
648 ValueIsNotValid (
649 IN BOOLEAN Complex,
650 IN UINT16 Value,
651 IN EFI_TAG *Tag,
652 IN EFI_FILE_FORM_TAGS *FileFormTags,
653 IN STRING_REF *PopUp
654 )
655 /*++
656
657 Routine Description:
658
659
660 Arguments:
661
662 Returns:
663
664 TRUE - If value is valid
665
666 FALSE - If value is not valid
667
668 --*/
669 {
670 BOOLEAN *StackPtr;
671 EFI_INCONSISTENCY_DATA *Iterator;
672 BOOLEAN Operator;
673 BOOLEAN Operator2;
674 UINTN Index;
675 VOID *BooleanExpression;
676 UINTN BooleanExpressionLength;
677 BOOLEAN NotOperator;
678 BOOLEAN OrOperator;
679 BOOLEAN AndOperator;
680 BOOLEAN ArtificialEnd;
681 UINT16 *MapBuffer;
682 UINT16 *MapBuffer2;
683 UINT16 MapValue;
684 UINT16 MapValue2;
685 UINTN SizeOfVariable;
686 CHAR16 VariableName[MAXIMUM_VALUE_CHARACTERS];
687 VOID *VariableData;
688 EFI_STATUS Status;
689 UINT16 Id;
690 UINT16 Width;
691 EFI_VARIABLE_DEFINITION *VariableDefinition;
692 BOOLEAN CosmeticConsistency;
693 UINT8 IsLegacy;
694
695 VariableData = NULL;
696 BooleanExpressionLength = 0;
697 BooleanExpression = NULL;
698 Operator = FALSE;
699 ArtificialEnd = FALSE;
700 CosmeticConsistency = TRUE;
701 IsLegacy = 0;
702
703 Id = Tag->Id;
704 if (Tag->StorageWidth == 1) {
705 Width = 1;
706 } else {
707 Width = 2;
708 }
709 CreateBooleanExpression (FileFormTags, Value, Id, Complex, &BooleanExpression, &BooleanExpressionLength);
710
711 if (mBooleanEvaluationStack == 0) {
712 InitializeBooleanEvaluator ();
713 }
714
715 if (BooleanExpression == NULL) {
716 return FALSE;
717 }
718
719 StackPtr = mBooleanEvaluationStack;
720 Iterator = BooleanExpression;
721 MapBuffer = NULL;
722 MapBuffer2 = NULL;
723 MapValue = 0;
724 MapValue2 = 0;
725
726 while (TRUE) {
727 NotOperator = FALSE;
728 OrOperator = FALSE;
729 AndOperator = FALSE;
730
731 if (Iterator->Operand == 0) {
732 return Operator;
733 }
734
735 //
736 // Because INVALID_OFFSET_VALUE - 1 is reserved for TRUE or FALSE, omit them.
737 //
738 if (Iterator->QuestionId1 != INVALID_OFFSET_VALUE &&
739 Iterator->QuestionId1 != INVALID_OFFSET_VALUE-1) {
740 ExtractNvValue (FileFormTags, Iterator->VariableNumber, Width, Iterator->QuestionId1, (VOID **) &MapBuffer);
741 ExtractNvValue (FileFormTags, Iterator->VariableNumber2, Width, Iterator->QuestionId2, (VOID **) &MapBuffer2);
742 if (MapBuffer != NULL) {
743 if (Width == 2) {
744 MapValue = *MapBuffer;
745 } else {
746 MapValue = (UINT8) *MapBuffer;
747 }
748
749 FreePool (MapBuffer);
750 }
751
752 if (MapBuffer2 != NULL) {
753 if (Width == 2) {
754 MapValue2 = *MapBuffer2;
755 } else {
756 MapValue2 = (UINT8) *MapBuffer2;
757 }
758
759 FreePool (MapBuffer2);
760 }
761 }
762
763 switch (Iterator->Operand) {
764 case EFI_IFR_SUPPRESS_IF_OP:
765 //
766 // Must have hit a suppress followed by a grayout or vice-versa
767 //
768 if (ArtificialEnd) {
769 ArtificialEnd = FALSE;
770 Operator = PopBool (&StackPtr);
771 if (Operator) {
772 Tag->Suppress = TRUE;
773 }
774
775 return Operator;
776 }
777
778 ArtificialEnd = TRUE;
779 *PopUp = Iterator->Popup;
780 break;
781
782 case EFI_IFR_GRAYOUT_IF_OP:
783 //
784 // Must have hit a suppress followed by a grayout or vice-versa
785 //
786 if (ArtificialEnd) {
787 ArtificialEnd = FALSE;
788 Operator = PopBool (&StackPtr);
789 if (Operator) {
790 Tag->GrayOut = TRUE;
791 }
792
793 return Operator;
794 }
795
796 ArtificialEnd = TRUE;
797 *PopUp = Iterator->Popup;
798 break;
799
800 case EFI_IFR_INCONSISTENT_IF_OP:
801 CosmeticConsistency = FALSE;
802 *PopUp = Iterator->Popup;
803 break;
804
805 //
806 // In the case of external variable values, we must read the variable which is
807 // named by the human readable version of the OpCode->VariableId and the guid of the formset
808 //
809 case EFI_IFR_EQ_VAR_VAL_OP:
810 //
811 // To check whether Ifr is legacy. Once every boolean expression.
812 //
813 if (IsLegacy == 0) {
814 IsLegacy = PredicateIfrType (Iterator);
815 }
816 if (IsLegacy == 0x2) {
817 PostOrderEvaluate (FileFormTags, Width, &Iterator, &StackPtr);
818 break;
819 }
820
821 UnicodeValueToString (
822 VariableName,
823 FALSE,
824 (UINTN) Iterator->QuestionId1,
825 (sizeof (VariableName) / sizeof (VariableName[0])) - 1
826 );
827
828 SizeOfVariable = 0;
829
830 ExtractRequestedNvMap (FileFormTags, Iterator->VariableNumber, &VariableDefinition);
831
832 Status = BooleanVariableWorker (
833 VariableName,
834 VariableDefinition,
835 StackPtr,
836 &SizeOfVariable,
837 &VariableData
838 );
839
840 if (!EFI_ERROR (Status)) {
841 if (SizeOfVariable == 1) {
842 CopyMem (&MapValue, VariableData, 1);
843 } else {
844 CopyMem (&MapValue, VariableData, 2);
845 }
846
847 PushBool (&StackPtr, (BOOLEAN) (MapValue == Iterator->Value));
848 }
849
850 break;
851
852 case EFI_IFR_EQ_ID_VAL_OP:
853 //
854 // To check whether Ifr is legacy. Once every boolean expression.
855 //
856 if (IsLegacy == 0) {
857 IsLegacy = PredicateIfrType (Iterator);
858 }
859 if (IsLegacy == 0x2) {
860 PostOrderEvaluate (FileFormTags, Width, &Iterator, &StackPtr);
861 break;
862 }
863
864 PushBool (&StackPtr, (BOOLEAN) (MapValue == Iterator->Value));
865 break;
866
867 case EFI_IFR_EQ_ID_ID_OP:
868 //
869 // To check whether Ifr is legacy. Once every boolean expression.
870 //
871 if (IsLegacy == 0) {
872 IsLegacy = PredicateIfrType (Iterator);
873 }
874 if (IsLegacy == 0x2) {
875 PostOrderEvaluate (FileFormTags, Width, &Iterator, &StackPtr);
876 break;
877 }
878
879 PushBool (&StackPtr, (BOOLEAN) (MapValue == MapValue2));
880 break;
881
882 case EFI_IFR_EQ_ID_LIST_OP:
883 //
884 // To check whether Ifr is legacy. Once every boolean expression.
885 //
886 if (IsLegacy == 0) {
887 IsLegacy = PredicateIfrType (Iterator);
888 }
889 if (IsLegacy == 0x2) {
890 PostOrderEvaluate (FileFormTags, Width, &Iterator, &StackPtr);
891 break;
892 }
893
894 for (Index = 0; Index < Iterator->ListLength; Index++) {
895 Operator = (BOOLEAN) (MapValue == Iterator->ValueList[Index]);
896 if (Operator) {
897 break;
898 }
899 }
900
901 PushBool (&StackPtr, Operator);
902 break;
903
904 case EFI_IFR_AND_OP:
905 Iterator++;
906 if (Iterator->Operand == EFI_IFR_NOT_OP) {
907 NotOperator = TRUE;
908 Iterator++;
909 }
910
911 if (Iterator->QuestionId1 != INVALID_OFFSET_VALUE) {
912 ExtractNvValue (FileFormTags, Iterator->VariableNumber, Width, Iterator->QuestionId1, (VOID **) &MapBuffer);
913 ExtractNvValue (FileFormTags, Iterator->VariableNumber2, Width, Iterator->QuestionId2, (VOID **) &MapBuffer2);
914 if (MapBuffer != NULL) {
915 if (Width == 2) {
916 MapValue = *MapBuffer;
917 } else {
918 MapValue = (UINT8) *MapBuffer;
919 }
920
921 FreePool (MapBuffer);
922 }
923
924 if (MapBuffer2 != NULL) {
925 if (Width == 2) {
926 MapValue2 = *MapBuffer2;
927 } else {
928 MapValue2 = (UINT8) *MapBuffer2;
929 }
930
931 FreePool (MapBuffer2);
932 }
933 }
934
935 switch (Iterator->Operand) {
936 case EFI_IFR_EQ_ID_VAL_OP:
937 //
938 // If Not - flip the results
939 //
940 if (NotOperator) {
941 Operator = (BOOLEAN)!(MapValue == Iterator->Value);
942 } else {
943 Operator = (BOOLEAN) (MapValue == Iterator->Value);
944 }
945
946 PushBool (&StackPtr, Operator);
947 break;
948
949 //
950 // In the case of external variable values, we must read the variable which is
951 // named by the human readable version of the OpCode->VariableId and the guid of the formset
952 //
953 case EFI_IFR_EQ_VAR_VAL_OP:
954 UnicodeValueToString (
955 VariableName,
956 FALSE,
957 (UINTN) Iterator->QuestionId1,
958 (sizeof (VariableName) / sizeof (VariableName[0])) - 1
959 );
960
961 SizeOfVariable = 0;
962
963 ExtractRequestedNvMap (FileFormTags, Iterator->VariableNumber, &VariableDefinition);
964
965 Status = BooleanVariableWorker (
966 VariableName,
967 VariableDefinition,
968 StackPtr,
969 &SizeOfVariable,
970 &VariableData
971 );
972
973 if (!EFI_ERROR (Status)) {
974 if (SizeOfVariable == 1) {
975 CopyMem (&MapValue, VariableData, 1);
976 } else {
977 CopyMem (&MapValue, VariableData, 2);
978 }
979 //
980 // If Not - flip the results
981 //
982 if (NotOperator) {
983 PushBool (&StackPtr, (BOOLEAN)!(MapValue == Iterator->Value));
984 } else {
985 PushBool (&StackPtr, (BOOLEAN) (MapValue == Iterator->Value));
986 }
987 }
988 break;
989
990 case EFI_IFR_EQ_ID_ID_OP:
991 //
992 // If Not - flip the results
993 //
994 if (NotOperator) {
995 Operator = (BOOLEAN)!(MapValue == MapValue2);
996 } else {
997 Operator = (BOOLEAN) (MapValue == MapValue2);
998 }
999
1000 PushBool (&StackPtr, Operator);
1001 break;
1002
1003 case EFI_IFR_EQ_ID_LIST_OP:
1004 for (Index = 0; Index < Iterator->ListLength; Index++) {
1005 //
1006 // If Not - flip the results
1007 //
1008 if (NotOperator) {
1009 Operator = (BOOLEAN)!(MapValue == Iterator->ValueList[Index]);
1010 } else {
1011 Operator = (BOOLEAN) (MapValue == Iterator->ValueList[Index]);
1012 }
1013 //
1014 // If We are trying to make sure that MapValue != Item[x], keep looking through
1015 // the list to make sure we don't equal any other items
1016 //
1017 if (Operator && NotOperator) {
1018 continue;
1019 }
1020 //
1021 // If MapValue == Item, then we have succeeded (first found is good enough)
1022 //
1023 if (Operator) {
1024 break;
1025 }
1026 }
1027
1028 PushBool (&StackPtr, Operator);
1029 break;
1030
1031 default:
1032 return FALSE;
1033 }
1034
1035 Operator = PopBool (&StackPtr);
1036 Operator2 = PopBool (&StackPtr);
1037 PushBool (&StackPtr, (BOOLEAN) (Operator && Operator2));
1038 break;
1039
1040 case EFI_IFR_OR_OP:
1041 Iterator++;
1042 if (Iterator->Operand == EFI_IFR_NOT_OP) {
1043 NotOperator = TRUE;
1044 Iterator++;
1045 }
1046
1047 if (Iterator->QuestionId1 != INVALID_OFFSET_VALUE) {
1048 ExtractNvValue (FileFormTags, Iterator->VariableNumber, Width, Iterator->QuestionId1, (VOID **) &MapBuffer);
1049 ExtractNvValue (FileFormTags, Iterator->VariableNumber2, Width, Iterator->QuestionId2, (VOID **) &MapBuffer2);
1050 if (MapBuffer != NULL) {
1051 if (Width == 2) {
1052 MapValue = *MapBuffer;
1053 } else {
1054 MapValue = (UINT8) *MapBuffer;
1055 }
1056
1057 FreePool (MapBuffer);
1058 }
1059
1060 if (MapBuffer2 != NULL) {
1061 if (Width == 2) {
1062 MapValue2 = *MapBuffer2;
1063 } else {
1064 MapValue2 = (UINT8) *MapBuffer2;
1065 }
1066
1067 FreePool (MapBuffer2);
1068 }
1069 }
1070
1071 switch (Iterator->Operand) {
1072 case EFI_IFR_EQ_ID_VAL_OP:
1073 //
1074 // If Not - flip the results
1075 //
1076 if (NotOperator) {
1077 Operator = (BOOLEAN)!(MapValue == Iterator->Value);
1078 } else {
1079 Operator = (BOOLEAN) (MapValue == Iterator->Value);
1080 }
1081
1082 PushBool (&StackPtr, Operator);
1083 break;
1084
1085 //
1086 // In the case of external variable values, we must read the variable which is
1087 // named by the human readable version of the OpCode->VariableId and the guid of the formset
1088 //
1089 case EFI_IFR_EQ_VAR_VAL_OP:
1090 UnicodeValueToString (
1091 VariableName,
1092 FALSE,
1093 (UINTN) Iterator->QuestionId1,
1094 (sizeof (VariableName) / sizeof (VariableName[0])) - 1
1095 );
1096
1097 SizeOfVariable = 0;
1098
1099 ExtractRequestedNvMap (FileFormTags, Iterator->VariableNumber, &VariableDefinition);
1100
1101 Status = BooleanVariableWorker (
1102 VariableName,
1103 VariableDefinition,
1104 StackPtr,
1105 &SizeOfVariable,
1106 &VariableData
1107 );
1108
1109 if (!EFI_ERROR (Status)) {
1110 if (SizeOfVariable == 1) {
1111 CopyMem (&MapValue, VariableData, 1);
1112 } else {
1113 CopyMem (&MapValue, VariableData, 2);
1114 }
1115 //
1116 // If Not - flip the results
1117 //
1118 if (NotOperator) {
1119 PushBool (&StackPtr, (BOOLEAN)!(MapValue == Iterator->Value));
1120 } else {
1121 PushBool (&StackPtr, (BOOLEAN) (MapValue == Iterator->Value));
1122 }
1123 }
1124 break;
1125
1126 case EFI_IFR_EQ_ID_ID_OP:
1127 //
1128 // If Not - flip the results
1129 //
1130 if (NotOperator) {
1131 Operator = (BOOLEAN)!(MapValue == MapValue2);
1132 } else {
1133 Operator = (BOOLEAN) (MapValue == MapValue2);
1134 }
1135
1136 PushBool (&StackPtr, Operator);
1137 break;
1138
1139 case EFI_IFR_EQ_ID_LIST_OP:
1140 for (Index = 0; Index < Iterator->ListLength; Index++) {
1141 //
1142 // If Not - flip the results
1143 //
1144 if (NotOperator) {
1145 Operator = (BOOLEAN)!(MapValue == Iterator->ValueList[Index]);
1146 } else {
1147 Operator = (BOOLEAN) (MapValue == Iterator->ValueList[Index]);
1148 }
1149 //
1150 // If We are trying to make sure that MapValue != Item[x], keep looking through
1151 // the list to make sure we don't equal any other items
1152 //
1153 if (Operator && NotOperator) {
1154 continue;
1155 }
1156 //
1157 // If MapValue == Item, then we have succeeded (first found is good enough)
1158 //
1159 if (Operator) {
1160 break;
1161 }
1162 }
1163
1164 PushBool (&StackPtr, Operator);
1165 break;
1166
1167 default:
1168 return FALSE;
1169 }
1170
1171 Operator = PopBool (&StackPtr);
1172 Operator2 = PopBool (&StackPtr);
1173 PushBool (&StackPtr, (BOOLEAN) (Operator || Operator2));
1174 break;
1175
1176 case EFI_IFR_NOT_OP:
1177 //
1178 // To check whether Ifr is legacy. Once every boolean expression.
1179 //
1180 if (IsLegacy == 0) {
1181 IsLegacy = PredicateIfrType (Iterator);
1182 }
1183 if (IsLegacy == 0x2) {
1184 PostOrderEvaluate (FileFormTags, Width, &Iterator, &StackPtr);
1185 break;
1186 }
1187
1188 //
1189 // I don't need to set the NotOperator (I know that I have to NOT this in this case
1190 //
1191 Iterator++;
1192
1193 if (Iterator->Operand == EFI_IFR_OR_OP) {
1194 OrOperator = TRUE;
1195 Iterator++;
1196 }
1197
1198 if (Iterator->Operand == EFI_IFR_AND_OP) {
1199 AndOperator = TRUE;
1200 Iterator++;
1201 }
1202
1203 if (Iterator->QuestionId1 != INVALID_OFFSET_VALUE) {
1204 ExtractNvValue (FileFormTags, Iterator->VariableNumber, Width, Iterator->QuestionId1, (VOID **) &MapBuffer);
1205 ExtractNvValue (FileFormTags, Iterator->VariableNumber2, Width, Iterator->QuestionId2, (VOID **) &MapBuffer2);
1206 if (MapBuffer != NULL) {
1207 if (Width == 2) {
1208 MapValue = *MapBuffer;
1209 } else {
1210 MapValue = (UINT8) *MapBuffer;
1211 }
1212
1213 FreePool (MapBuffer);
1214 }
1215
1216 if (MapBuffer2 != NULL) {
1217 if (Width == 2) {
1218 MapValue2 = *MapBuffer2;
1219 } else {
1220 MapValue2 = (UINT8) *MapBuffer2;
1221 }
1222
1223 FreePool (MapBuffer2);
1224 }
1225 }
1226
1227 switch (Iterator->Operand) {
1228 case EFI_IFR_EQ_ID_VAL_OP:
1229 Operator = (BOOLEAN)!(MapValue == Iterator->Value);
1230 PushBool (&StackPtr, Operator);
1231 break;
1232
1233 //
1234 // In the case of external variable values, we must read the variable which is
1235 // named by the human readable version of the OpCode->VariableId and the guid of the formset
1236 //
1237 case EFI_IFR_EQ_VAR_VAL_OP:
1238 UnicodeValueToString (
1239 VariableName,
1240 FALSE,
1241 (UINTN) Iterator->QuestionId1,
1242 (sizeof (VariableName) / sizeof (VariableName[0])) - 1
1243 );
1244
1245 SizeOfVariable = 0;
1246
1247 ExtractRequestedNvMap (FileFormTags, Iterator->VariableNumber, &VariableDefinition);
1248
1249 Status = BooleanVariableWorker (
1250 VariableName,
1251 VariableDefinition,
1252 StackPtr,
1253 &SizeOfVariable,
1254 &VariableData
1255 );
1256
1257 if (!EFI_ERROR (Status)) {
1258 if (SizeOfVariable == 1) {
1259 CopyMem (&MapValue, VariableData, 1);
1260 } else {
1261 CopyMem (&MapValue, VariableData, 2);
1262 }
1263
1264 PushBool (&StackPtr, (BOOLEAN)!(MapValue == Iterator->Value));
1265 }
1266 break;
1267
1268 case EFI_IFR_EQ_ID_ID_OP:
1269 Operator = (BOOLEAN)!(MapValue == MapValue2);
1270 PushBool (&StackPtr, Operator);
1271 break;
1272
1273 case EFI_IFR_EQ_ID_LIST_OP:
1274 for (Index = 0; Index < Iterator->ListLength; Index++) {
1275 Operator = (BOOLEAN)!(MapValue == Iterator->ValueList[Index]);
1276 if (Operator) {
1277 continue;
1278 }
1279 }
1280
1281 PushBool (&StackPtr, Operator);
1282 break;
1283
1284 default:
1285 return FALSE;
1286 }
1287
1288 Operator = PopBool (&StackPtr);
1289 Operator2 = PopBool (&StackPtr);
1290
1291 if (OrOperator) {
1292 PushBool (&StackPtr, (BOOLEAN) (Operator || Operator2));
1293 }
1294
1295 if (AndOperator) {
1296 PushBool (&StackPtr, (BOOLEAN) (Operator && Operator2));
1297 }
1298
1299 if (!OrOperator && !AndOperator) {
1300 PushBool (&StackPtr, Operator);
1301 }
1302 break;
1303
1304 case EFI_IFR_TRUE_OP:
1305 //
1306 // To check whether Ifr is legacy. Once every boolean expression.
1307 //
1308 if (IsLegacy == 0) {
1309 IsLegacy = PredicateIfrType (Iterator);
1310 }
1311 if (IsLegacy == 0x2) {
1312 PostOrderEvaluate (FileFormTags, Width, &Iterator, &StackPtr);
1313 break;
1314 }
1315 break;
1316
1317 case EFI_IFR_FALSE_OP:
1318 //
1319 // To check whether Ifr is legacy. Once every boolean expression.
1320 //
1321 if (IsLegacy == 0) {
1322 IsLegacy = PredicateIfrType (Iterator);
1323 }
1324 if (IsLegacy == 0x2) {
1325 PostOrderEvaluate (FileFormTags, Width, &Iterator, &StackPtr);
1326 break;
1327 }
1328 break;
1329
1330 case EFI_IFR_END_IF_OP:
1331 Operator = PopBool (&StackPtr);
1332 //
1333 // If there is an error, return, otherwise keep looking - there might
1334 // be another test that causes an error
1335 //
1336 if (Operator) {
1337 if (Complex && CosmeticConsistency) {
1338 return EFI_SUCCESS;
1339 } else {
1340 return Operator;
1341 }
1342 } else {
1343 //
1344 // If not doing a global consistency check, the endif is the REAL terminator of this operation
1345 // This is used for grayout/suppress operations. InconsistentIf is a global operation so the EndIf is
1346 // not the end-all be-all of terminators.
1347 //
1348 if (!Complex) {
1349 return Operator;
1350 }
1351 break;
1352 }
1353
1354 default:
1355 //
1356 // Must have hit a non-consistency related op-code after a suppress/grayout
1357 //
1358 if (ArtificialEnd) {
1359 ArtificialEnd = FALSE;
1360 Operator = PopBool (&StackPtr);
1361 return Operator;
1362 }
1363
1364 goto Done;
1365 }
1366
1367 Iterator++;
1368 }
1369
1370 Done:
1371 return FALSE;
1372 }