EFI_STATUS EFIAPI StartGauge ( IN EFI_PERFORMANCE_PROTOCOL *This, IN EFI_HANDLE Handle, IN UINT16 *Token, IN UINT16 *Host, IN UINT64 Ticker ) /*++ Routine Description: Create a guage data node and initialized it. Arguments: This - Calling context Handle - Handle of gauge data Token - Token of gauge data Host - Host of gauge data Ticker - Set gauge data's StartTick. If 0, StartTick is current timer. Returns: EFI_SUCCESS - Successfully create and initialized a guage data node. EFI_OUT_OF_RESOURCES - No enough resource to create a guage data node. --*/ { EFI_PERFORMANCE_INSTANCE *PerfInstance; EFI_PERF_DATA_LIST *Node; UINT64 TimerValue; TimerValue = 0; PerfInstance = EFI_PERFORMANCE_FROM_THIS (This); Node = CreateDataNode (Handle, Token, Host); if (!Node) { return EFI_OUT_OF_RESOURCES; } if (Ticker != 0) { TimerValue = Ticker; } else { GetTimerValue (&TimerValue); } Node->GaugeData.StartTick = TimerValue; if (!EfiStrCmp (Token, DXE_TOK)) { PerfInstance->Phase = DXE_PHASE; } if (!EfiStrCmp (Token, SHELL_TOK)) { PerfInstance->Phase = SHELL_PHASE; } Node->GaugeData.Phase = PerfInstance->Phase; InsertTailList (&mPerfDataHead, &(Node->Link)); return EFI_SUCCESS; }
EFI_PERF_DATA_LIST * GetDataNode ( IN EFI_HANDLE Handle, IN UINT16 *Token, IN UINT16 *Host, IN EFI_GUID *GuidName, IN EFI_GAUGE_DATA *PrevGauge ) /*++ Routine Description: Search gauge node list to find one node with matched handle, token, host and Guid name. Arguments: Handle - Handle to match Token - Token to match Host - Host to match GuidName - Guid name to match PrevGauge - Start node, start from list head if NULL Returns: Return pointer to the node found, NULL if not found. --*/ { EFI_PERF_DATA_LIST *Node; EFI_PERF_DATA_LIST *Temp; EFI_PERF_DATA_LIST *Temp2; EFI_LIST_ENTRY *CurrentLink; EFI_GUID NullGuid = EFI_NULL_GUID; Node = NULL; Temp = NULL; Temp2 = NULL; if (PrevGauge == NULL) { CurrentLink = mPerfDataHead.ForwardLink; } else { Temp2 = GAUGE_DATA_FROM_GAUGE (PrevGauge); CurrentLink = (Temp2->Link).ForwardLink; } while (CurrentLink && CurrentLink != &mPerfDataHead) { Node = GAUGE_DATA_FROM_LINK (CurrentLink); if (Handle == 0 && Token == NULL && Host == NULL && GuidName == NULL) { return Node; } if (Handle != (Node->GaugeData).Handle) { CurrentLink = CurrentLink->ForwardLink; continue; } if (GuidName == NULL && !EfiCompareGuid (&((Node->GaugeData).GuidName), &NullGuid)) { CurrentLink = CurrentLink->ForwardLink; continue; } if (GuidName && !EfiCompareGuid (&((Node->GaugeData).GuidName), GuidName)) { CurrentLink = CurrentLink->ForwardLink; continue; } if (Token == NULL && EfiStrCmp (Node->GaugeData.Token, L"")) { CurrentLink = CurrentLink->ForwardLink; continue; } if (Token && EfiStrCmp (Node->GaugeData.Token, Token)) { CurrentLink = CurrentLink->ForwardLink; continue; } if (Host == NULL && EfiStrCmp (Node->GaugeData.Host, L"")) { CurrentLink = CurrentLink->ForwardLink; continue; } if (Host && EfiStrCmp (Node->GaugeData.Host, Host)) { CurrentLink = CurrentLink->ForwardLink; continue; } Temp = Node; break; } return Temp; }
EFI_STATUS BBTestGetAltCfgFunctionTestCheckpoint1 ( IN EFI_STANDARD_TEST_LIBRARY_PROTOCOL *StandardLib, IN EFI_HII_CONFIG_ROUTING_PROTOCOL *HIIConfigRouting ) { EFI_TEST_ASSERTION AssertionType; EFI_STATUS Status; EFI_STRING ConfigAltResp; EFI_GUID Guid1 = { 0x4ab90e97, 0xd4a0, 0xf749, 0xb9, 0x80, 0xbd, 0xaa, 0x47, 0xd4, 0x25, 0x27}; EFI_GUID Guid2 = { 0x4ab90e97, 0xd4a0, 0xf749, 0xb9, 0x80, 0xbd, 0xaa, 0x47, 0xd4, 0x25, 0x28}; EFI_STRING NameDomain1 = L"jin9"; //L"006a0069006e0039"; EFI_STRING NameDomain2 = L"jin8"; //L"006a0069006e0038"; UINT16 AltCfgId1 = EFI_HII_DEFAULT_CLASS_STANDARD; UINT16 AltCfgId2 = EFI_HII_DEFAULT_CLASS_MANUFACTURING; EFI_STRING CfgResp = NULL; ConfigAltResp = L"GUID=970eb94aa0d449f7b980bdaa47d42527&NAME=006a0069006e0039&PATH=000ace&OFFSET=3&WIDTH=4&VALUE=aabbccdd&OFFSET=1&WIDTH=2&VALUE=1122&GUID=970eb94aa0d449f7b980bdaa47d42527&NAME=006a0069006e0039&PATH=000ace&ALTCFG=0000&a000=abcd&b000=efef&GUID=970eb94aa0d449f7b980bdaa47d42528&NAME=006a0069006e0038&PATH=000acf&ALTCFG=0001&OFFSET=3&WIDTH=4&VALUE=aabbccdd&OFFSET=1&WIDTH=2&VALUE=eeff"; // GUID=970eb94aa0d449f7b980bdaa47d42527&NAME=006a0069006e0039&PATH=000ace&OFFSET=3&WIDTH=4&VALUE=aabbccdd&OFFSET=1&WIDTH=2&VALUE=eeff //&GUID=970eb94aa0d449f7b980bdaa47d42527&NAME=006a0069006e0039&PATH=000ace&ALTCFG=0037&a000=abcd&b000=efef //&GUID=970eb94aa0d449f7b980bdaa47d42528&NAME=006a0069006e0038&PATH=000acf&a000=abcd&b000=efef //&GUID=970eb94aa0d449f7b980bdaa47d42528&NAME=006a0069006e0038&PATH=000acf&ALTCFG=0038&OFFSET=3&WIDTH=4&VALUE=aabbccdd&OFFSET=1&WIDTH=2&VALUE=eeff // Check All are NULL, except AltcfgId Status = HIIConfigRouting->GetAltCfg( HIIConfigRouting, ConfigAltResp, NULL, NULL, NULL, &AltCfgId1, &CfgResp ); if ( EFI_SUCCESS == Status ) { if (0 != EfiStrCmp(CfgResp, L"GUID=970eb94aa0d449f7b980bdaa47d42527&NAME=006a0069006e0039&PATH=000ace&a000=abcd&b000=efef")){ AssertionType = EFI_TEST_ASSERTION_FAILED; } else { AssertionType = EFI_TEST_ASSERTION_PASSED; } if (CfgResp != NULL) { gtBS->FreePool(CfgResp); CfgResp = NULL; } } else if ( EFI_OUT_OF_RESOURCES == Status ){ AssertionType = EFI_TEST_ASSERTION_WARNING; } else { AssertionType = EFI_TEST_ASSERTION_FAILED; } StandardLib->RecordAssertion ( StandardLib, AssertionType, gHIIConfigRoutingBBTestFunctionAssertionGuid006, L"HII_CONFIG_ROUTING_PROTOCOL.GetAltCfg - GetAltCfg() returns EFI_SUCCESS with valid AltcfgId1.", L"%a:%d: Status - %r", __FILE__, (UINTN)__LINE__, Status ); // Check Guid1 Status = HIIConfigRouting->GetAltCfg( HIIConfigRouting, ConfigAltResp, &Guid1, NULL, NULL, &AltCfgId1, &CfgResp ); if ( EFI_SUCCESS == Status ) { if (0 != EfiStrCmp(CfgResp, L"GUID=970eb94aa0d449f7b980bdaa47d42527&NAME=006a0069006e0039&PATH=000ace&a000=abcd&b000=efef")){ AssertionType = EFI_TEST_ASSERTION_FAILED; } else { AssertionType = EFI_TEST_ASSERTION_PASSED; } if (CfgResp != NULL) { gtBS->FreePool(CfgResp); CfgResp = NULL; } } else if ( EFI_OUT_OF_RESOURCES == Status ){ AssertionType = EFI_TEST_ASSERTION_WARNING; } else { AssertionType = EFI_TEST_ASSERTION_FAILED; } StandardLib->RecordAssertion ( StandardLib, AssertionType, gHIIConfigRoutingBBTestFunctionAssertionGuid007, L"HII_CONFIG_ROUTING_PROTOCOL.GetAltCfg - GetAltCfg() returns EFI_SUCCESS with valid Guid1 and AltcfgId1.", L"%a:%d: Status - %r", __FILE__, (UINTN)__LINE__, Status ); // Check NameDomain1 Status = HIIConfigRouting->GetAltCfg( HIIConfigRouting, ConfigAltResp, NULL, NameDomain1, NULL, &AltCfgId1, &CfgResp ); if ( EFI_SUCCESS == Status ) { if (0 != EfiStrCmp(CfgResp, L"GUID=970eb94aa0d449f7b980bdaa47d42527&NAME=006a0069006e0039&PATH=000ace&a000=abcd&b000=efef")) { AssertionType = EFI_TEST_ASSERTION_FAILED; } else { AssertionType = EFI_TEST_ASSERTION_PASSED; } if (CfgResp != NULL) { gtBS->FreePool(CfgResp); CfgResp = NULL; } } else if ( EFI_OUT_OF_RESOURCES == Status ){ AssertionType = EFI_TEST_ASSERTION_WARNING; } else { AssertionType = EFI_TEST_ASSERTION_FAILED; } StandardLib->RecordAssertion ( StandardLib, AssertionType, gHIIConfigRoutingBBTestFunctionAssertionGuid008, L"HII_CONFIG_ROUTING_PROTOCOL.GetAltCfg - GetAltCfg() returns EFI_SUCCESS with valid Name1 and AltcfgId1.", L"%a:%d: Status - %r", __FILE__, (UINTN)__LINE__, Status ); // Check NameDomain1 and Guid1 Status = HIIConfigRouting->GetAltCfg( HIIConfigRouting, ConfigAltResp, &Guid1, NameDomain1, NULL, &AltCfgId1, &CfgResp ); if ( EFI_SUCCESS == Status ) { if (0 != EfiStrCmp(CfgResp, L"GUID=970eb94aa0d449f7b980bdaa47d42527&NAME=006a0069006e0039&PATH=000ace&a000=abcd&b000=efef")) { AssertionType = EFI_TEST_ASSERTION_FAILED; } else { AssertionType = EFI_TEST_ASSERTION_PASSED; } if (CfgResp != NULL) { gtBS->FreePool(CfgResp); CfgResp = NULL; } } else if ( EFI_OUT_OF_RESOURCES == Status ){ AssertionType = EFI_TEST_ASSERTION_WARNING; } else { AssertionType = EFI_TEST_ASSERTION_FAILED; } StandardLib->RecordAssertion ( StandardLib, AssertionType, gHIIConfigRoutingBBTestFunctionAssertionGuid009, L"HII_CONFIG_ROUTING_PROTOCOL.GetAltCfg - GetAltCfg() returns EFI_SUCCESS with valid Guid1, Name1, and AltCfgId1.", L"%a:%d: Status - %r", __FILE__, (UINTN)__LINE__, Status ); // Check NameDomain1 and Guid1, with AltCfgId is NULL Status = HIIConfigRouting->GetAltCfg( HIIConfigRouting, ConfigAltResp, &Guid1, NameDomain1, NULL, NULL, &CfgResp ); if ( EFI_SUCCESS == Status ) { if (0 != EfiStrCmp(CfgResp, L"GUID=970eb94aa0d449f7b980bdaa47d42527&NAME=006a0069006e0039&PATH=000ace&OFFSET=3&WIDTH=4&VALUE=aabbccdd&OFFSET=1&WIDTH=2&VALUE=1122")) { AssertionType = EFI_TEST_ASSERTION_FAILED; } else { AssertionType = EFI_TEST_ASSERTION_PASSED; } if (CfgResp != NULL) { gtBS->FreePool(CfgResp); CfgResp = NULL; } } else if ( EFI_OUT_OF_RESOURCES == Status ){ AssertionType = EFI_TEST_ASSERTION_WARNING; } else { AssertionType = EFI_TEST_ASSERTION_FAILED; } StandardLib->RecordAssertion ( StandardLib, AssertionType, gHIIConfigRoutingBBTestFunctionAssertionGuid010, L"HII_CONFIG_ROUTING_PROTOCOL.GetAltCfg - GetAltCfg() returns EFI_SUCCESS with valid Guid1 and Name1.", L"%a:%d: Status - %r", __FILE__, (UINTN)__LINE__, Status ); // Check NameDomain1 only Status = HIIConfigRouting->GetAltCfg( HIIConfigRouting, ConfigAltResp, NULL, NameDomain1, NULL, NULL, &CfgResp ); if ( EFI_SUCCESS == Status ) { if (0 != EfiStrCmp(CfgResp, L"GUID=970eb94aa0d449f7b980bdaa47d42527&NAME=006a0069006e0039&PATH=000ace&OFFSET=3&WIDTH=4&VALUE=aabbccdd&OFFSET=1&WIDTH=2&VALUE=1122")) { AssertionType = EFI_TEST_ASSERTION_FAILED; } else { AssertionType = EFI_TEST_ASSERTION_PASSED; } if (CfgResp != NULL) { gtBS->FreePool(CfgResp); CfgResp = NULL; } } else if ( EFI_OUT_OF_RESOURCES == Status ){ AssertionType = EFI_TEST_ASSERTION_WARNING; } else { AssertionType = EFI_TEST_ASSERTION_FAILED; } StandardLib->RecordAssertion ( StandardLib, AssertionType, gHIIConfigRoutingBBTestFunctionAssertionGuid012, L"HII_CONFIG_ROUTING_PROTOCOL.GetAltCfg - GetAltCfg() returns EFI_SUCCESS with valid Name1.", L"%a:%d: Status - %r", __FILE__, (UINTN)__LINE__, Status ); /****************************************************************************************/ // // Check All are NULL, except AltcfgId // current setting will be returned // Status = HIIConfigRouting->GetAltCfg( HIIConfigRouting, ConfigAltResp, NULL, NULL, NULL, &AltCfgId2, &CfgResp ); if ( EFI_SUCCESS == Status ) { if (0 != EfiStrCmp(CfgResp, L"GUID=970eb94aa0d449f7b980bdaa47d42528&NAME=006a0069006e0038&PATH=000acf&OFFSET=3&WIDTH=4&VALUE=aabbccdd&OFFSET=1&WIDTH=2&VALUE=eeff")) { AssertionType = EFI_TEST_ASSERTION_FAILED; } else { AssertionType = EFI_TEST_ASSERTION_PASSED; } if (CfgResp != NULL) { gtBS->FreePool(CfgResp); CfgResp = NULL; } } else if ( EFI_OUT_OF_RESOURCES == Status ){ AssertionType = EFI_TEST_ASSERTION_WARNING; } else { AssertionType = EFI_TEST_ASSERTION_FAILED; } StandardLib->RecordAssertion ( StandardLib, AssertionType, gHIIConfigRoutingBBTestFunctionAssertionGuid006, L"HII_CONFIG_ROUTING_PROTOCOL.GetAltCfg - GetAltCfg() returns EFI_SUCCESS with valid AltcfgId2.", L"%a:%d: Status - %r", __FILE__, (UINTN)__LINE__, Status ); // Check Guid2 Status = HIIConfigRouting->GetAltCfg( HIIConfigRouting, ConfigAltResp, &Guid2, NULL, NULL, &AltCfgId2, &CfgResp ); if ( EFI_SUCCESS == Status ) { if (0 != EfiStrCmp(CfgResp, L"GUID=970eb94aa0d449f7b980bdaa47d42528&NAME=006a0069006e0038&PATH=000acf&OFFSET=3&WIDTH=4&VALUE=aabbccdd&OFFSET=1&WIDTH=2&VALUE=eeff")){ AssertionType = EFI_TEST_ASSERTION_FAILED; } else { AssertionType = EFI_TEST_ASSERTION_PASSED; } if (CfgResp != NULL) { gtBS->FreePool(CfgResp); CfgResp = NULL; } } else if ( EFI_OUT_OF_RESOURCES == Status ){ AssertionType = EFI_TEST_ASSERTION_WARNING; } else { AssertionType = EFI_TEST_ASSERTION_FAILED; } StandardLib->RecordAssertion ( StandardLib, AssertionType, gHIIConfigRoutingBBTestFunctionAssertionGuid007, L"HII_CONFIG_ROUTING_PROTOCOL.GetAltCfg - GetAltCfg() returns EFI_SUCCESS with valid Guid2 and AltcfgId2.", L"%a:%d: Status - %r", __FILE__, (UINTN)__LINE__, Status ); // Check NameDomain2 Status = HIIConfigRouting->GetAltCfg( HIIConfigRouting, ConfigAltResp, NULL, NameDomain2, NULL, &AltCfgId2, &CfgResp ); if ( EFI_SUCCESS == Status ) { if (0 != EfiStrCmp(CfgResp, L"GUID=970eb94aa0d449f7b980bdaa47d42528&NAME=006a0069006e0038&PATH=000acf&OFFSET=3&WIDTH=4&VALUE=aabbccdd&OFFSET=1&WIDTH=2&VALUE=eeff")) { AssertionType = EFI_TEST_ASSERTION_FAILED; } else { AssertionType = EFI_TEST_ASSERTION_PASSED; } if (CfgResp != NULL) { gtBS->FreePool(CfgResp); CfgResp = NULL; } } else if ( EFI_OUT_OF_RESOURCES == Status ){ AssertionType = EFI_TEST_ASSERTION_WARNING; } else { AssertionType = EFI_TEST_ASSERTION_FAILED; } StandardLib->RecordAssertion ( StandardLib, AssertionType, gHIIConfigRoutingBBTestFunctionAssertionGuid008, L"HII_CONFIG_ROUTING_PROTOCOL.GetAltCfg - GetAltCfg() returns EFI_SUCCESS with valid Name2 and AltcfgId2.", L"%a:%d: Status - %r", __FILE__, (UINTN)__LINE__, Status ); // Check NameDomain2 and Guid2 Status = HIIConfigRouting->GetAltCfg( HIIConfigRouting, ConfigAltResp, &Guid2, NameDomain2, NULL, &AltCfgId2, &CfgResp ); if ( EFI_SUCCESS == Status ) { if (0 != EfiStrCmp(CfgResp, L"GUID=970eb94aa0d449f7b980bdaa47d42528&NAME=006a0069006e0038&PATH=000acf&OFFSET=3&WIDTH=4&VALUE=aabbccdd&OFFSET=1&WIDTH=2&VALUE=eeff")) { AssertionType = EFI_TEST_ASSERTION_FAILED; } else { AssertionType = EFI_TEST_ASSERTION_PASSED; } if (CfgResp != NULL) { gtBS->FreePool(CfgResp); CfgResp = NULL; } } else if ( EFI_OUT_OF_RESOURCES == Status ){ AssertionType = EFI_TEST_ASSERTION_WARNING; } else { AssertionType = EFI_TEST_ASSERTION_FAILED; } StandardLib->RecordAssertion ( StandardLib, AssertionType, gHIIConfigRoutingBBTestFunctionAssertionGuid009, L"HII_CONFIG_ROUTING_PROTOCOL.GetAltCfg - GetAltCfg() returns EFI_SUCCESS with valid Guid2, Name2 and AltcfgId2.", L"%a:%d: Status - %r", __FILE__, (UINTN)__LINE__, Status ); return EFI_SUCCESS; }
EFI_STATUS ProcessOptions ( IN UI_MENU_SELECTION *Selection, IN UI_MENU_OPTION *MenuOption, IN BOOLEAN Selected, OUT CHAR16 **OptionString ) /*++ Routine Description: Process a Question's Option (whether selected or un-selected). Arguments: Selection - Pointer to UI_MENU_SELECTION. MenuOption - The MenuOption for this Question. Selected - TRUE: if Question is selected. OptionString - Pointer of the Option String to be displayed. Returns: EFI_SUCCESS - Question Option process success. Other - Question Option process fail. --*/ { EFI_STATUS Status; CHAR16 *StringPtr; CHAR16 *TempString; UINTN Index; FORM_BROWSER_STATEMENT *Question; CHAR16 FormattedNumber[21]; UINT16 Number; CHAR16 Character[2]; EFI_INPUT_KEY Key; UINTN BufferSize; QUESTION_OPTION *OneOfOption; EFI_LIST_ENTRY *Link; EFI_HII_VALUE HiiValue; EFI_HII_VALUE *QuestionValue; BOOLEAN Suppress; UINT16 Minimum; UINT16 Maximum; QUESTION_OPTION *Option; UINTN Index2; UINT8 *ValueArray; UINT8 ValueType; Status = EFI_SUCCESS; StringPtr = NULL; Character[1] = L'\0'; *OptionString = NULL; EfiZeroMem (FormattedNumber, 21 * sizeof (CHAR16)); BufferSize = (gOptionBlockWidth + 1) * 2 * gScreenDimensions.BottomRow; Question = MenuOption->ThisTag; QuestionValue = &Question->HiiValue; Minimum = (UINT16) Question->Minimum; Maximum = (UINT16) Question->Maximum; ValueArray = Question->BufferValue; ValueType = Question->ValueType; switch (Question->Operand) { case EFI_IFR_ORDERED_LIST_OP: // // Check whether there are Options of this OrderedList // if (IsListEmpty (&Question->OptionListHead)) { break; } // // Initialize Option value array // if (GetArrayData (ValueArray, ValueType, 0) == 0) { GetQuestionDefault (Selection->FormSet, Selection->Form, Question, 0); } if (Selected) { // // Go ask for input // Status = GetSelectionInputPopUp (Selection, MenuOption); } else { // // We now know how many strings we will have, so we can allocate the // space required for the array or strings. // *OptionString = EfiLibAllocateZeroPool (Question->MaxContainers * BufferSize); ASSERT (*OptionString); HiiValue.Type = ValueType; HiiValue.Value.u64 = 0; for (Index = 0; Index < Question->MaxContainers; Index++) { HiiValue.Value.u64 = GetArrayData (ValueArray, ValueType, Index); if (HiiValue.Value.u64 == 0) { // // Values for the options in ordered lists should never be a 0 // break; } OneOfOption = ValueToOption (Question, &HiiValue); if (OneOfOption == NULL) { // // Show error message // do { CreateDialog (4, TRUE, 0, NULL, &Key, gEmptyString, gOptionMismatch, gPressEnter, gEmptyString); } while (Key.UnicodeChar != CHAR_CARRIAGE_RETURN); // // The initial value of the orderedlist is invalid, force to be valid value // Link = GetFirstNode (&Question->OptionListHead); Index2 = 0; while (!IsNull (&Question->OptionListHead, Link) && Index2 < Question->MaxContainers) { Option = QUESTION_OPTION_FROM_LINK (Link); SetArrayData (ValueArray, ValueType, Index2, Option->Value.Value.u64); Index2++; Link = GetNextNode (&Question->OptionListHead, Link); } SetArrayData (ValueArray, ValueType, Index2, 0); Status = SetQuestionValue (Selection->FormSet, Selection->Form, Question, TRUE); UpdateStatusBar (NV_UPDATE_REQUIRED, Question->QuestionFlags, TRUE); gBS->FreePool (*OptionString); *OptionString = NULL; return EFI_NOT_FOUND; } Suppress = FALSE; if ((OneOfOption->SuppressExpression != NULL) && (OneOfOption->SuppressExpression->Result.Value.b)) { // // This option is suppressed // Suppress = TRUE; } if (!Suppress) { Character[0] = LEFT_ONEOF_DELIMITER; NewStrCat (OptionString[0], Character); StringPtr = GetToken (OneOfOption->Text, Selection->Handle); NewStrCat (OptionString[0], StringPtr); Character[0] = RIGHT_ONEOF_DELIMITER; NewStrCat (OptionString[0], Character); Character[0] = CHAR_CARRIAGE_RETURN; NewStrCat (OptionString[0], Character); gBS->FreePool (StringPtr); } } } break; case EFI_IFR_ONE_OF_OP: // // Check whether there are Options of this OneOf // if (IsListEmpty (&Question->OptionListHead)) { break; } if (Selected) { // // Go ask for input // Status = GetSelectionInputPopUp (Selection, MenuOption); } else { *OptionString = EfiLibAllocateZeroPool (BufferSize); ASSERT (*OptionString); OneOfOption = ValueToOption (Question, QuestionValue); if (OneOfOption == NULL) { // // Show error message // do { CreateDialog (4, TRUE, 0, NULL, &Key, gEmptyString, gOptionMismatch, gPressEnter, gEmptyString); } while (Key.UnicodeChar != CHAR_CARRIAGE_RETURN); // // Force the Question value to be valid // Link = GetFirstNode (&Question->OptionListHead); while (!IsNull (&Question->OptionListHead, Link)) { Option = QUESTION_OPTION_FROM_LINK (Link); if ((Option->SuppressExpression == NULL) || !Option->SuppressExpression->Result.Value.b) { EfiCopyMem (QuestionValue, &Option->Value, sizeof (EFI_HII_VALUE)); SetQuestionValue (Selection->FormSet, Selection->Form, Question, TRUE); UpdateStatusBar (NV_UPDATE_REQUIRED, Question->QuestionFlags, TRUE); break; } Link = GetNextNode (&Question->OptionListHead, Link); } gBS->FreePool (*OptionString); *OptionString = NULL; return EFI_NOT_FOUND; } if ((OneOfOption->SuppressExpression != NULL) && (OneOfOption->SuppressExpression->Result.Value.b)) { // // This option is suppressed // Suppress = TRUE; } else { Suppress = FALSE; } if (Suppress) { // // Current selected option happen to be suppressed, // enforce to select on a non-suppressed option // Link = GetFirstNode (&Question->OptionListHead); while (!IsNull (&Question->OptionListHead, Link)) { OneOfOption = QUESTION_OPTION_FROM_LINK (Link); if ((OneOfOption->SuppressExpression == NULL) || !OneOfOption->SuppressExpression->Result.Value.b) { Suppress = FALSE; EfiCopyMem (QuestionValue, &OneOfOption->Value, sizeof (EFI_HII_VALUE)); SetQuestionValue (Selection->FormSet, Selection->Form, Question, TRUE); UpdateStatusBar (NV_UPDATE_REQUIRED, Question->QuestionFlags, TRUE); gST->ConOut->SetAttribute (gST->ConOut, FIELD_TEXT | FIELD_BACKGROUND); break; } Link = GetNextNode (&Question->OptionListHead, Link); } } if (!Suppress) { Character[0] = LEFT_ONEOF_DELIMITER; NewStrCat (OptionString[0], Character); StringPtr = GetToken (OneOfOption->Text, Selection->Handle); NewStrCat (OptionString[0], StringPtr); Character[0] = RIGHT_ONEOF_DELIMITER; NewStrCat (OptionString[0], Character); gBS->FreePool (StringPtr); } } break; case EFI_IFR_CHECKBOX_OP: *OptionString = EfiLibAllocateZeroPool (BufferSize); ASSERT (*OptionString); *OptionString[0] = LEFT_CHECKBOX_DELIMITER; if (Selected) { // // Since this is a BOOLEAN operation, flip it upon selection // QuestionValue->Value.b = QuestionValue->Value.b ? FALSE : TRUE; // // Perform inconsistent check // Status = ValidateQuestion (Selection->FormSet, Selection->Form, Question, EFI_HII_EXPRESSION_INCONSISTENT_IF); if (EFI_ERROR (Status)) { // // Inconsistent check fail, restore Question Value // QuestionValue->Value.b = QuestionValue->Value.b ? FALSE : TRUE; gBS->FreePool (*OptionString); *OptionString = NULL; return Status; } // // Save Question value // Status = SetQuestionValue (Selection->FormSet, Selection->Form, Question, TRUE); UpdateStatusBar (NV_UPDATE_REQUIRED, Question->QuestionFlags, TRUE); } if (QuestionValue->Value.b) { *(OptionString[0] + 1) = CHECK_ON; } else { *(OptionString[0] + 1) = CHECK_OFF; } *(OptionString[0] + 2) = RIGHT_CHECKBOX_DELIMITER; break; case EFI_IFR_NUMERIC_OP: if (Selected) { // // Go ask for input // Status = GetNumericInput (Selection, MenuOption); } else { *OptionString = EfiLibAllocateZeroPool (BufferSize); ASSERT (*OptionString); *OptionString[0] = LEFT_NUMERIC_DELIMITER; // // Formatted print // PrintFormattedNumber (Question, FormattedNumber, 21 * sizeof (CHAR16)); Number = (UINT16) GetStringWidth (FormattedNumber); EfiCopyMem (OptionString[0] + 1, FormattedNumber, Number); *(OptionString[0] + Number / 2) = RIGHT_NUMERIC_DELIMITER; } break; case EFI_IFR_DATE_OP: if (Selected) { // // This is similar to numerics // Status = GetNumericInput (Selection, MenuOption); } else { *OptionString = EfiLibAllocateZeroPool (BufferSize); ASSERT (*OptionString); switch (MenuOption->Sequence) { case 0: *OptionString[0] = LEFT_NUMERIC_DELIMITER; SPrint (OptionString[0] + 1, 21 * sizeof (CHAR16), L"%02d", (UINTN) QuestionValue->Value.date.Month); *(OptionString[0] + 3) = DATE_SEPARATOR; break; case 1: SetUnicodeMem (OptionString[0], 4, L' '); SPrint (OptionString[0] + 4, 21 * sizeof (CHAR16), L"%02d", (UINTN) QuestionValue->Value.date.Day); *(OptionString[0] + 6) = DATE_SEPARATOR; break; case 2: SetUnicodeMem (OptionString[0], 7, L' '); SPrint (OptionString[0] + 7, 21 * sizeof (CHAR16), L"%4d", (UINTN) QuestionValue->Value.date.Year); *(OptionString[0] + 11) = RIGHT_NUMERIC_DELIMITER; break; } } break; case EFI_IFR_TIME_OP: if (Selected) { // // This is similar to numerics // Status = GetNumericInput (Selection, MenuOption); } else { *OptionString = EfiLibAllocateZeroPool (BufferSize); ASSERT (*OptionString); switch (MenuOption->Sequence) { case 0: *OptionString[0] = LEFT_NUMERIC_DELIMITER; SPrint (OptionString[0] + 1, 21 * sizeof (CHAR16), L"%02d", (UINTN) QuestionValue->Value.time.Hour); *(OptionString[0] + 3) = TIME_SEPARATOR; break; case 1: SetUnicodeMem (OptionString[0], 4, L' '); SPrint (OptionString[0] + 4, 21 * sizeof (CHAR16), L"%02d", (UINTN) QuestionValue->Value.time.Minute); *(OptionString[0] + 6) = TIME_SEPARATOR; break; case 2: SetUnicodeMem (OptionString[0], 7, L' '); SPrint (OptionString[0] + 7, 21 * sizeof (CHAR16), L"%02d", (UINTN) QuestionValue->Value.time.Second); *(OptionString[0] + 9) = RIGHT_NUMERIC_DELIMITER; break; } } break; case EFI_IFR_STRING_OP: if (Selected) { StringPtr = EfiLibAllocateZeroPool ((Maximum + 1) * sizeof (CHAR16)); ASSERT (StringPtr); Status = ReadString (MenuOption, gPromptForData, StringPtr); if (!EFI_ERROR (Status)) { EfiCopyMem (Question->BufferValue, StringPtr, Maximum * sizeof (CHAR16)); SetQuestionValue (Selection->FormSet, Selection->Form, Question, TRUE); UpdateStatusBar (NV_UPDATE_REQUIRED, Question->QuestionFlags, TRUE); } gBS->FreePool (StringPtr); } else { *OptionString = EfiLibAllocateZeroPool (BufferSize); ASSERT (*OptionString); if (((CHAR16 *) Question->BufferValue)[0] == 0x0000) { *(OptionString[0]) = '_'; } else { if ((Maximum * sizeof (CHAR16)) < BufferSize) { BufferSize = Maximum * sizeof (CHAR16); } EfiCopyMem (OptionString[0], (CHAR16 *) Question->BufferValue, BufferSize); } } break; case EFI_IFR_PASSWORD_OP: if (Selected) { StringPtr = EfiLibAllocateZeroPool ((Maximum + 1) * sizeof (CHAR16)); ASSERT (StringPtr); // // For interactive passwords, old password is validated by callback // if (Question->QuestionFlags & EFI_IFR_FLAG_CALLBACK) { // // Use a NULL password to test whether old password is required // *StringPtr = 0; Status = PasswordCallback (Selection, MenuOption, StringPtr); if (Status == EFI_NOT_AVAILABLE_YET) { // // Callback request to terminate password input // gBS->FreePool (StringPtr); return EFI_SUCCESS; } if (EFI_ERROR (Status)) { // // Old password exist, ask user for the old password // Status = ReadString (MenuOption, gPromptForPassword, StringPtr); if (EFI_ERROR (Status)) { gBS->FreePool (StringPtr); return Status; } // // Check user input old password // Status = PasswordCallback (Selection, MenuOption, StringPtr); if (EFI_ERROR (Status)) { if (Status == EFI_NOT_READY) { // // Typed in old password incorrect // PasswordInvalid (); } else { Status = EFI_SUCCESS; } gBS->FreePool (StringPtr); return Status; } } } else { // // For non-interactive password, validate old password in local // if (*((CHAR16 *) Question->BufferValue) != 0) { // // There is something there! Prompt for password // Status = ReadString (MenuOption, gPromptForPassword, StringPtr); if (EFI_ERROR (Status)) { gBS->FreePool (StringPtr); return Status; } TempString = EfiLibAllocateCopyPool ((Maximum + 1) * sizeof (CHAR16), Question->BufferValue); TempString[Maximum] = L'\0'; if (EfiStrCmp (StringPtr, TempString) != 0) { // // Typed in old password incorrect // PasswordInvalid (); gBS->FreePool (StringPtr); gBS->FreePool (TempString); return Status; } gBS->FreePool (TempString); } } // // Ask for new password // EfiZeroMem (StringPtr, (Maximum + 1) * sizeof (CHAR16)); Status = ReadString (MenuOption, gPromptForNewPassword, StringPtr); if (EFI_ERROR (Status)) { // // Reset state machine for interactive password // if (Question->QuestionFlags & EFI_IFR_FLAG_CALLBACK) { PasswordCallback (Selection, MenuOption, NULL); } gBS->FreePool (StringPtr); return Status; } // // Confirm new password // TempString = EfiLibAllocateZeroPool ((Maximum + 1) * sizeof (CHAR16)); ASSERT (TempString); Status = ReadString (MenuOption, gConfirmPassword, TempString); if (EFI_ERROR (Status)) { // // Reset state machine for interactive password // if (Question->QuestionFlags & EFI_IFR_FLAG_CALLBACK) { PasswordCallback (Selection, MenuOption, NULL); } gBS->FreePool (StringPtr); gBS->FreePool (TempString); return Status; } // // Compare two typed-in new passwords // if (EfiStrCmp (StringPtr, TempString) == 0) { // // Two password match, send it to Configuration Driver // if (Question->QuestionFlags & EFI_IFR_FLAG_CALLBACK) { PasswordCallback (Selection, MenuOption, StringPtr); } else { EfiCopyMem (Question->BufferValue, StringPtr, Maximum * sizeof (CHAR16)); SetQuestionValue (Selection->FormSet, Selection->Form, Question, FALSE); } } else { // // Reset state machine for interactive password // if (Question->QuestionFlags & EFI_IFR_FLAG_CALLBACK) { PasswordCallback (Selection, MenuOption, NULL); } // // Two password mismatch, prompt error message // do { CreateDialog (4, TRUE, 0, NULL, &Key, gEmptyString, gConfirmError, gPressEnter, gEmptyString); } while (Key.UnicodeChar != CHAR_CARRIAGE_RETURN); } gBS->FreePool (TempString); gBS->FreePool (StringPtr); } break; default: break; } return Status; }
EFI_STATUS EvaluateExpression ( IN FORM_BROWSER_FORMSET *FormSet, IN FORM_BROWSER_FORM *Form, IN OUT FORM_EXPRESSION *Expression ) /*++ Routine Description: Evaluate the result of a HII expression Arguments: FormSet - FormSet associated with this expression. Form - Form associated with this expression. Expression - Expression to be evaluated. Returns: EFI_SUCCESS - The expression evaluated successfuly EFI_NOT_FOUND - The Question which referenced by a QuestionId could not be found. EFI_OUT_OF_RESOURCES - There is not enough system memory to grow the stack. EFI_ACCESS_DENIED - The pop operation underflowed the stack EFI_INVALID_PARAMETER - Syntax error with the Expression --*/ { EFI_STATUS Status; EFI_LIST_ENTRY *Link; EXPRESSION_OPCODE *OpCode; FORM_BROWSER_STATEMENT *Question; FORM_BROWSER_STATEMENT *Question2; UINT16 Index; EFI_HII_VALUE Data1; EFI_HII_VALUE Data2; EFI_HII_VALUE Data3; FORM_EXPRESSION *RuleExpression; EFI_HII_VALUE *Value; INTN Result; CHAR16 *StrPtr; // // Always reset the stack before evaluating an Expression // ResetExpressionStack (); Expression->Result.Type = EFI_IFR_TYPE_OTHER; Link = GetFirstNode (&Expression->OpCodeListHead); while (!IsNull (&Expression->OpCodeListHead, Link)) { OpCode = EXPRESSION_OPCODE_FROM_LINK (Link); Link = GetNextNode (&Expression->OpCodeListHead, Link); EfiZeroMem (&Data1, sizeof (EFI_HII_VALUE)); EfiZeroMem (&Data2, sizeof (EFI_HII_VALUE)); EfiZeroMem (&Data3, sizeof (EFI_HII_VALUE)); Value = &Data3; Value->Type = EFI_IFR_TYPE_BOOLEAN; Status = EFI_SUCCESS; switch (OpCode->Operand) { // // Built-in functions // case EFI_IFR_EQ_ID_VAL_OP: Question = IdToQuestion (FormSet, Form, OpCode->QuestionId); if (Question == NULL) { return EFI_NOT_FOUND; } Result = CompareHiiValue (&Question->HiiValue, &OpCode->Value, NULL); if (Result == EFI_INVALID_PARAMETER) { return EFI_INVALID_PARAMETER; } Value->Value.b = (Result == 0) ? TRUE : FALSE; break; case EFI_IFR_EQ_ID_ID_OP: Question = IdToQuestion (FormSet, Form, OpCode->QuestionId); if (Question == NULL) { return EFI_NOT_FOUND; } Question2 = IdToQuestion (FormSet, Form, OpCode->QuestionId2); if (Question2 == NULL) { return EFI_NOT_FOUND; } Result = CompareHiiValue (&Question->HiiValue, &Question2->HiiValue, FormSet->HiiHandle); if (Result == EFI_INVALID_PARAMETER) { return EFI_INVALID_PARAMETER; } Value->Value.b = (Result == 0) ? TRUE : FALSE; break; case EFI_IFR_EQ_ID_LIST_OP: Question = IdToQuestion (FormSet, Form, OpCode->QuestionId); if (Question == NULL) { return EFI_NOT_FOUND; } Value->Value.b = FALSE; for (Index =0; Index < OpCode->ListLength; Index++) { if (Question->HiiValue.Value.u16 == OpCode->ValueList[Index]) { Value->Value.b = TRUE; break; } } break; case EFI_IFR_DUP_OP: Status = PopExpression (Value); if (EFI_ERROR (Status)) { return Status; } Status = PushExpression (Value); break; case EFI_IFR_QUESTION_REF1_OP: case EFI_IFR_THIS_OP: Question = IdToQuestion (FormSet, Form, OpCode->QuestionId); if (Question == NULL) { return EFI_NOT_FOUND; } Value = &Question->HiiValue; break; case EFI_IFR_QUESTION_REF3_OP: if (OpCode->DevicePath == 0) { // // EFI_IFR_QUESTION_REF3 // Pop an expression from the expression stack // Status = PopExpression (Value); if (EFI_ERROR (Status)) { return Status; } // // Validate the expression value // if ((Value->Type > EFI_IFR_TYPE_NUM_SIZE_64) || (Value->Value.u64 > 0xffff)) { return EFI_NOT_FOUND; } Question = IdToQuestion (FormSet, Form, Value->Value.u16); if (Question == NULL) { return EFI_NOT_FOUND; } // // push the questions' value on to the expression stack // Value = &Question->HiiValue; } else { // // BUGBUG: push 0 for EFI_IFR_QUESTION_REF3_2 and EFI_IFR_QUESTION_REF3_3, // since it is impractical to evaluate the value of a Question in another // Hii Package list. // EfiZeroMem (Value, sizeof (EFI_HII_VALUE)); } break; case EFI_IFR_RULE_REF_OP: // // Find expression for this rule // RuleExpression = RuleIdToExpression (Form, OpCode->RuleId); if (RuleExpression == NULL) { return EFI_NOT_FOUND; } // // Evaluate this rule expression // Status = EvaluateExpression (FormSet, Form, RuleExpression); if (EFI_ERROR (Status)) { return Status; } Value = &RuleExpression->Result; break; case EFI_IFR_STRING_REF1_OP: Value->Type = EFI_IFR_TYPE_STRING; Value->Value.string = OpCode->Value.Value.string; break; // // Constant // case EFI_IFR_TRUE_OP: case EFI_IFR_FALSE_OP: case EFI_IFR_ONE_OP: case EFI_IFR_ONES_OP: case EFI_IFR_UINT8_OP: case EFI_IFR_UINT16_OP: case EFI_IFR_UINT32_OP: case EFI_IFR_UINT64_OP: case EFI_IFR_UNDEFINED_OP: case EFI_IFR_VERSION_OP: case EFI_IFR_ZERO_OP: Value = &OpCode->Value; break; // // unary-op // case EFI_IFR_LENGTH_OP: Status = PopExpression (Value); if (EFI_ERROR (Status)) { return Status; } if (Value->Type != EFI_IFR_TYPE_STRING) { return EFI_INVALID_PARAMETER; } StrPtr = GetToken (Value->Value.string, FormSet->HiiHandle); if (StrPtr == NULL) { return EFI_INVALID_PARAMETER; } Value->Type = EFI_IFR_TYPE_NUM_SIZE_64; Value->Value.u64 = EfiStrLen (StrPtr); gBS->FreePool (StrPtr); break; case EFI_IFR_NOT_OP: Status = PopExpression (Value); if (EFI_ERROR (Status)) { return Status; } if (Value->Type != EFI_IFR_TYPE_BOOLEAN) { return EFI_INVALID_PARAMETER; } Value->Value.b = !Value->Value.b; break; case EFI_IFR_QUESTION_REF2_OP: // // Pop an expression from the expression stack // Status = PopExpression (Value); if (EFI_ERROR (Status)) { return Status; } // // Validate the expression value // if ((Value->Type > EFI_IFR_TYPE_NUM_SIZE_64) || (Value->Value.u64 > 0xffff)) { return EFI_NOT_FOUND; } Question = IdToQuestion (FormSet, Form, Value->Value.u16); if (Question == NULL) { return EFI_NOT_FOUND; } Value = &Question->HiiValue; break; case EFI_IFR_STRING_REF2_OP: // // Pop an expression from the expression stack // Status = PopExpression (Value); if (EFI_ERROR (Status)) { return Status; } // // Validate the expression value // if ((Value->Type > EFI_IFR_TYPE_NUM_SIZE_64) || (Value->Value.u64 > 0xffff)) { return EFI_NOT_FOUND; } Value->Type = EFI_IFR_TYPE_STRING; StrPtr = GetToken (Value->Value.u16, FormSet->HiiHandle); if (StrPtr == NULL) { // // If String not exit, push an empty string // Value->Value.string = NewString (gEmptyString, FormSet->HiiHandle); } else { Index = (UINT16) Value->Value.u64; Value->Value.string = Index; gBS->FreePool (StrPtr); } break; case EFI_IFR_TO_BOOLEAN_OP: // // Pop an expression from the expression stack // Status = PopExpression (Value); if (EFI_ERROR (Status)) { return Status; } // // Convert an expression to a Boolean // if (Value->Type <= EFI_IFR_TYPE_DATE) { // // When converting from an unsigned integer, zero will be converted to // FALSE and any other value will be converted to TRUE. // Value->Value.b = (Value->Value.u64) ? TRUE : FALSE; Value->Type = EFI_IFR_TYPE_BOOLEAN; } else if (Value->Type == EFI_IFR_TYPE_STRING) { // // When converting from a string, if case-insensitive compare // with "true" is True, then push True. If a case-insensitive compare // with "false" is True, then push False. // StrPtr = GetToken (Value->Value.string, FormSet->HiiHandle); if (StrPtr == NULL) { return EFI_INVALID_PARAMETER; } if ((EfiStrCmp (StrPtr, L"true") == 0) || (EfiStrCmp (StrPtr, L"false") == 0)){ Value->Value.b = TRUE; } else { Value->Value.b = FALSE; } gBS->FreePool (StrPtr); Value->Type = EFI_IFR_TYPE_BOOLEAN; } break; case EFI_IFR_TO_STRING_OP: Status = IfrToString (FormSet, OpCode->Format, Value); break; case EFI_IFR_TO_UINT_OP: Status = IfrToUint (FormSet, Value); break; case EFI_IFR_TO_LOWER_OP: case EFI_IFR_TO_UPPER_OP: Status = InitializeUnicodeCollationProtocol (); if (EFI_ERROR (Status)) { return Status; } Status = PopExpression (Value); if (EFI_ERROR (Status)) { return Status; } if (Value->Type != EFI_IFR_TYPE_STRING) { return EFI_UNSUPPORTED; } StrPtr = GetToken (Value->Value.string, FormSet->HiiHandle); if (StrPtr == NULL) { return EFI_NOT_FOUND; } if (OpCode->Operand == EFI_IFR_TO_LOWER_OP) { mUnicodeCollation->StrLwr (mUnicodeCollation, StrPtr); } else { mUnicodeCollation->StrUpr (mUnicodeCollation, StrPtr); } Value->Value.string = NewString (StrPtr, FormSet->HiiHandle); gBS->FreePool (StrPtr); break; case EFI_IFR_BITWISE_NOT_OP: // // Pop an expression from the expression stack // Status = PopExpression (Value); if (EFI_ERROR (Status)) { return Status; } if (Value->Type > EFI_IFR_TYPE_DATE) { return EFI_INVALID_PARAMETER; } Value->Type = EFI_IFR_TYPE_NUM_SIZE_64; Value->Value.u64 = ~Value->Value.u64; break; // // binary-op // case EFI_IFR_ADD_OP: case EFI_IFR_SUBTRACT_OP: case EFI_IFR_MULTIPLY_OP: case EFI_IFR_DIVIDE_OP: case EFI_IFR_MODULO_OP: case EFI_IFR_BITWISE_AND_OP: case EFI_IFR_BITWISE_OR_OP: case EFI_IFR_SHIFT_LEFT_OP: case EFI_IFR_SHIFT_RIGHT_OP: // // Pop an expression from the expression stack // Status = PopExpression (&Data2); if (EFI_ERROR (Status)) { return Status; } if (Data2.Type > EFI_IFR_TYPE_DATE) { return EFI_INVALID_PARAMETER; } // // Pop another expression from the expression stack // Status = PopExpression (&Data1); if (EFI_ERROR (Status)) { return Status; } if (Data1.Type > EFI_IFR_TYPE_DATE) { return EFI_INVALID_PARAMETER; } Value->Type = EFI_IFR_TYPE_NUM_SIZE_64; switch (OpCode->Operand) { case EFI_IFR_ADD_OP: Value->Value.u64 = Data1.Value.u64 + Data2.Value.u64; break; case EFI_IFR_SUBTRACT_OP: Value->Value.u64 = Data1.Value.u64 - Data2.Value.u64; break; case EFI_IFR_MULTIPLY_OP: Value->Value.u64 = MultU64x32 (Data1.Value.u64, (UINTN) Data2.Value.u64); break; case EFI_IFR_DIVIDE_OP: Value->Value.u64 = DivU64x32 (Data1.Value.u64, (UINTN) Data2.Value.u64, NULL); break; case EFI_IFR_MODULO_OP: DivU64x32 (Data1.Value.u64, (UINTN) Data2.Value.u64, (UINTN *) &Value->Value.u64); break; case EFI_IFR_BITWISE_AND_OP: Value->Value.u64 = Data1.Value.u64 & Data2.Value.u64; break; case EFI_IFR_BITWISE_OR_OP: Value->Value.u64 = Data1.Value.u64 | Data2.Value.u64; break; case EFI_IFR_SHIFT_LEFT_OP: Value->Value.u64 = LShiftU64 (Data1.Value.u64, (UINTN) Data2.Value.u64); break; case EFI_IFR_SHIFT_RIGHT_OP: Value->Value.u64 = RShiftU64 (Data1.Value.u64, (UINTN) Data2.Value.u64); break; default: break; } break; case EFI_IFR_AND_OP: case EFI_IFR_OR_OP: // // Two Boolean operator // Status = PopExpression (&Data2); if (EFI_ERROR (Status)) { return Status; } if (Data2.Type != EFI_IFR_TYPE_BOOLEAN) { return EFI_INVALID_PARAMETER; } // // Pop another expression from the expression stack // Status = PopExpression (&Data1); if (EFI_ERROR (Status)) { return Status; } if (Data1.Type != EFI_IFR_TYPE_BOOLEAN) { return EFI_INVALID_PARAMETER; } if (OpCode->Operand == EFI_IFR_AND_OP) { Value->Value.b = Data1.Value.b && Data2.Value.b; } else { Value->Value.b = Data1.Value.b || Data2.Value.b; } break; case EFI_IFR_EQUAL_OP: case EFI_IFR_NOT_EQUAL_OP: case EFI_IFR_GREATER_EQUAL_OP: case EFI_IFR_GREATER_THAN_OP: case EFI_IFR_LESS_EQUAL_OP: case EFI_IFR_LESS_THAN_OP: // // Compare two integer, string, boolean or date/time // Status = PopExpression (&Data2); if (EFI_ERROR (Status)) { return Status; } if (Data2.Type > EFI_IFR_TYPE_BOOLEAN && Data2.Type != EFI_IFR_TYPE_STRING) { return EFI_INVALID_PARAMETER; } // // Pop another expression from the expression stack // Status = PopExpression (&Data1); if (EFI_ERROR (Status)) { return Status; } Result = CompareHiiValue (&Data1, &Data2, FormSet->HiiHandle); if (Result == EFI_INVALID_PARAMETER) { return EFI_INVALID_PARAMETER; } switch (OpCode->Operand) { case EFI_IFR_EQUAL_OP: Value->Value.b = (Result == 0) ? TRUE : FALSE; break; case EFI_IFR_NOT_EQUAL_OP: Value->Value.b = (Result != 0) ? TRUE : FALSE; break; case EFI_IFR_GREATER_EQUAL_OP: Value->Value.b = (Result >= 0) ? TRUE : FALSE; break; case EFI_IFR_GREATER_THAN_OP: Value->Value.b = (Result > 0) ? TRUE : FALSE; break; case EFI_IFR_LESS_EQUAL_OP: Value->Value.b = (Result <= 0) ? TRUE : FALSE; break; case EFI_IFR_LESS_THAN_OP: Value->Value.b = (Result < 0) ? TRUE : FALSE; break; default: break; } break; case EFI_IFR_MATCH_OP: Status = IfrMatch (FormSet, Value); break; case EFI_IFR_CATENATE_OP: Status = IfrCatenate (FormSet, Value); break; // // ternary-op // case EFI_IFR_CONDITIONAL_OP: // // Pop third expression from the expression stack // Status = PopExpression (&Data3); if (EFI_ERROR (Status)) { return Status; } // // Pop second expression from the expression stack // Status = PopExpression (&Data2); if (EFI_ERROR (Status)) { return Status; } // // Pop first expression from the expression stack // Status = PopExpression (&Data1); if (EFI_ERROR (Status)) { return Status; } if (Data1.Type != EFI_IFR_TYPE_BOOLEAN) { return EFI_INVALID_PARAMETER; } if (Data1.Value.b) { Value = &Data3; } else { Value = &Data2; } break; case EFI_IFR_FIND_OP: Status = IfrFind (FormSet, OpCode->Format, Value); break; case EFI_IFR_MID_OP: Status = IfrMid (FormSet, Value); break; case EFI_IFR_TOKEN_OP: Status = IfrToken (FormSet, Value); break; case EFI_IFR_SPAN_OP: Status = IfrSpan (FormSet, OpCode->Flags, Value); break; default: break; } if (EFI_ERROR (Status)) { return Status; } Status = PushExpression (Value); if (EFI_ERROR (Status)) { return Status; } } // // Pop the final result from expression stack // Value = &Data1; Status = PopExpression (Value); if (EFI_ERROR (Status)) { return Status; } // // After evaluating an expression, there should be only one value left on the expression stack // if (PopExpression (Value) != EFI_ACCESS_DENIED) { return EFI_INVALID_PARAMETER; } EfiCopyMem (&Expression->Result, Value, sizeof (EFI_HII_VALUE)); return EFI_SUCCESS; }
INTN CompareHiiValue ( IN EFI_HII_VALUE *Value1, IN EFI_HII_VALUE *Value2, IN EFI_HII_HANDLE HiiHandle OPTIONAL ) /*++ Routine Description: Compare two Hii value. Arguments: Value1 - Expression value to compare on left-hand Value2 - Expression value to compare on right-hand HiiHandle - Only required for string compare Returns: EFI_INVALID_PARAMETER - Could not perform comparation on two values 0 - Two operators equeal < 0 - Value1 is greater than Value2 > 0 - Value1 is less than Value2 --*/ { INTN Result; INT64 Temp64; CHAR16 *Str1; CHAR16 *Str2; if (Value1->Type >= EFI_IFR_TYPE_OTHER || Value2->Type >= EFI_IFR_TYPE_OTHER ) { return EFI_INVALID_PARAMETER; } if (Value1->Type == EFI_IFR_TYPE_STRING || Value2->Type == EFI_IFR_TYPE_STRING ) { if (Value1->Type != Value2->Type) { // // Both Operator should be type of String // return EFI_INVALID_PARAMETER; } if (Value1->Value.string == 0 || Value2->Value.string == 0) { // // StringId 0 is reserved // return EFI_INVALID_PARAMETER; } if (Value1->Value.string == Value2->Value.string) { return 0; } Str1 = GetToken (Value1->Value.string, HiiHandle); if (Str1 == NULL) { // // String not found // return EFI_INVALID_PARAMETER; } Str2 = GetToken (Value2->Value.string, HiiHandle); if (Str2 == NULL) { gBS->FreePool (Str1); return EFI_INVALID_PARAMETER; } Result = EfiStrCmp (Str1, Str2); gBS->FreePool (Str1); gBS->FreePool (Str2); return Result; } // // Take remain types(integer, boolean, date/time) as integer // Temp64 = (INT64) (Value1->Value.u64 - Value2->Value.u64); if (Temp64 > 0) { Result = 1; } else if (Temp64 < 0) { Result = -1; } else { Result = 0; } return Result; }