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