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