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