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