1/** @file 2Utility functions for expression evaluation. 3 4Copyright (c) 2007 - 2015, Intel Corporation. All rights reserved.<BR> 5This program and the accompanying materials 6are licensed and made available under the terms and conditions of the BSD License 7which accompanies this distribution. The full text of the license may be found at 8http://opensource.org/licenses/bsd-license.php 9 10THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, 11WITHOUT 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// 20EFI_HII_VALUE *mOpCodeScopeStack = NULL; 21EFI_HII_VALUE *mOpCodeScopeStackEnd = NULL; 22EFI_HII_VALUE *mOpCodeScopeStackPointer = NULL; 23 24EFI_HII_VALUE *mExpressionEvaluationStack = NULL; 25EFI_HII_VALUE *mExpressionEvaluationStackEnd = NULL; 26EFI_HII_VALUE *mExpressionEvaluationStackPointer = NULL; 27UINTN mExpressionEvaluationStackOffset = 0; 28 29EFI_HII_VALUE *mCurrentExpressionStack = NULL; 30EFI_HII_VALUE *mCurrentExpressionEnd = NULL; 31EFI_HII_VALUE *mCurrentExpressionPointer = NULL; 32 33EFI_HII_VALUE *mMapExpressionListStack = NULL; 34EFI_HII_VALUE *mMapExpressionListEnd = NULL; 35EFI_HII_VALUE *mMapExpressionListPointer = NULL; 36 37FORM_EXPRESSION **mFormExpressionStack = NULL; 38FORM_EXPRESSION **mFormExpressionEnd = NULL; 39FORM_EXPRESSION **mFormExpressionPointer = NULL; 40 41FORM_EXPRESSION **mStatementExpressionStack = NULL; 42FORM_EXPRESSION **mStatementExpressionEnd = NULL; 43FORM_EXPRESSION **mStatementExpressionPointer = NULL; 44 45FORM_EXPRESSION **mOptionExpressionStack = NULL; 46FORM_EXPRESSION **mOptionExpressionEnd = NULL; 47FORM_EXPRESSION **mOptionExpressionPointer = NULL; 48 49 50// 51// Unicode collation protocol interface 52// 53EFI_UNICODE_COLLATION_PROTOCOL *mUnicodeCollation = NULL; 54EFI_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**/ 70EFI_STATUS 71GrowStack ( 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**/ 129EFI_STATUS 130PushStack ( 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**/ 178EFI_STATUS 179PopStack ( 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**/ 205VOID 206ResetCurrentExpressionStack ( 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**/ 226EFI_STATUS 227PushCurrentExpression ( 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**/ 254EFI_STATUS 255PopCurrentExpression ( 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**/ 277VOID 278ResetMapExpressionListStack ( 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**/ 301EFI_STATUS 302GrowConditionalStack ( 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**/ 360EFI_STATUS 361PushConditionalStack ( 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**/ 404EFI_STATUS 405PopConditionalStack ( 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**/ 437INTN 438GetConditionalExpressionCount ( 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**/ 464FORM_EXPRESSION ** 465GetConditionalExpressionList ( 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**/ 494EFI_STATUS 495PushConditionalExpression ( 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**/ 538EFI_STATUS 539PopConditionalExpression ( 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**/ 583EFI_STATUS 584PushMapExpressionList ( 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**/ 611EFI_STATUS 612PopMapExpressionList ( 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**/ 634VOID 635ResetScopeStack ( 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**/ 653EFI_STATUS 654PushScope ( 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**/ 682EFI_STATUS 683PopScope ( 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**/ 712EFI_STATUS 713PushExpression ( 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**/ 735EFI_STATUS 736PopExpression ( 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**/ 752UINTN 753SaveExpressionEvaluationStackOffset ( 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**/ 768VOID 769RestoreExpressionEvaluationStackOffset ( 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**/ 786FORM_BROWSER_FORM * 787IdToForm ( 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**/ 820FORM_BROWSER_STATEMENT * 821IdToQuestion2 ( 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**/ 862FORM_BROWSER_STATEMENT * 863IdToQuestion ( 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**/ 917FORM_EXPRESSION * 918RuleIdToExpression ( 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**/ 948EFI_STATUS 949InitializeUnicodeCollationProtocol ( 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**/ 978VOID 979IfrStrToUpper ( 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**/ 1003BOOLEAN 1004IsTypeInBuffer ( 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**/ 1029BOOLEAN 1030IsTypeInUINT64 ( 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**/ 1058UINT16 1059GetLengthForValue ( 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**/ 1092UINT8 * 1093GetBufferForValue ( 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**/ 1126EFI_STATUS 1127IfrToString ( 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**/ 1239EFI_STATUS 1240IfrToUint ( 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**/ 1312EFI_STATUS 1313IfrCatenate ( 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 } 1391Done: 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**/ 1422EFI_STATUS 1423IfrMatch ( 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 1469Done: 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**/ 1491EFI_STATUS 1492IfrMatch2 ( 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 1639Done: 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**/ 1666EFI_STATUS 1667IfrFind ( 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 1742Done: 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**/ 1764EFI_STATUS 1765IfrMid ( 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**/ 1865EFI_STATUS 1866IfrToken ( 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 1956Done: 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**/ 1979EFI_STATUS 1980IfrSpan ( 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 2075Done: 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**/ 2093VOID 2094ExtendValueToU64 ( 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**/ 2141UINT64 2142HiiValueToUINT64 ( 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**/ 2198EFI_STATUS 2199CompareHiiValue ( 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**/ 2298BOOLEAN 2299CheckUserPrivilege ( 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**/ 2405BOOLEAN 2406GetQuestionValueFromForm ( 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 2494Done: 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**/ 2523EFI_STATUS 2524EvaluateExpression ( 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 3608Done: 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**/ 3629BOOLEAN 3630IsTrue ( 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**/ 3669EXPRESS_RESULT 3670EvaluateExpressionList ( 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