diff --git a/MdeModulePkg/Include/Protocol/DisplayProtocol.h b/MdeModulePkg/Include/Protocol/DisplayProtocol.h index f8b80f5e4a..664c227768 100644 --- a/MdeModulePkg/Include/Protocol/DisplayProtocol.h +++ b/MdeModulePkg/Include/Protocol/DisplayProtocol.h @@ -36,6 +36,8 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. #define BROWSER_FORM_NOT_FOUND BROWSER_ERROR | 0x03 #define BROWSER_FORM_SUPPRESS BROWSER_ERROR | 0x04 #define BROWSER_PROTOCOL_NOT_FOUND BROWSER_ERROR | 0x05 +#define BROWSER_INCONSISTENT_IF BROWSER_ERROR | 0x06 +#define BROWSER_WARNING_IF BROWSER_ERROR | 0x07 #define FORM_DISPLAY_ENGINE_STATEMENT_VERSION_1 0x10000 #define FORM_DISPLAY_ENGINE_VERSION_1 0x10000 diff --git a/MdeModulePkg/Universal/DisplayEngineDxe/FormDisplay.c b/MdeModulePkg/Universal/DisplayEngineDxe/FormDisplay.c index fe3d875cd9..df0fbfee7c 100644 --- a/MdeModulePkg/Universal/DisplayEngineDxe/FormDisplay.c +++ b/MdeModulePkg/Universal/DisplayEngineDxe/FormDisplay.c @@ -3197,14 +3197,53 @@ BrowserStatusProcess ( VOID ) { - CHAR16 *ErrorInfo; - EFI_INPUT_KEY Key; + CHAR16 *ErrorInfo; + EFI_INPUT_KEY Key; + EFI_EVENT WaitList[2]; + EFI_EVENT RefreshIntervalEvent; + EFI_EVENT TimeOutEvent; + UINT8 TimeOut; + EFI_STATUS Status; + UINTN Index; + WARNING_IF_CONTEXT EventContext; + EFI_IFR_OP_HEADER *OpCodeBuf; + EFI_STRING_ID StringToken; if (gFormData->BrowserStatus == BROWSER_SUCCESS) { return; } - if (gFormData->ErrorString != NULL) { + StringToken = 0; + TimeOutEvent = NULL; + RefreshIntervalEvent = NULL; + OpCodeBuf = NULL; + if (gFormData->HighLightedStatement != NULL) { + OpCodeBuf = gFormData->HighLightedStatement->OpCode; + } + + if (gFormData->BrowserStatus == (BROWSER_WARNING_IF)) { + ASSERT (OpCodeBuf != NULL && OpCodeBuf->OpCode == EFI_IFR_WARNING_IF_OP); + + TimeOut = ((EFI_IFR_WARNING_IF *) OpCodeBuf)->TimeOut; + StringToken = ((EFI_IFR_WARNING_IF *) OpCodeBuf)->Warning; + } else { + TimeOut = 0; + if ((gFormData->BrowserStatus == (BROWSER_NO_SUBMIT_IF)) && + (OpCodeBuf != NULL && OpCodeBuf->OpCode == EFI_IFR_NO_SUBMIT_IF_OP)) { + StringToken = ((EFI_IFR_NO_SUBMIT_IF *) OpCodeBuf)->Error; + } else if ((gFormData->BrowserStatus == (BROWSER_INCONSISTENT_IF)) && + (OpCodeBuf != NULL && OpCodeBuf->OpCode == EFI_IFR_INCONSISTENT_IF_OP)) { + StringToken = ((EFI_IFR_INCONSISTENT_IF *) OpCodeBuf)->Error; + } + } + + if (StringToken != 0) { + ErrorInfo = GetToken (StringToken, gFormData->HiiHandle); + } else if (gFormData->ErrorString != NULL) { + // + // Only used to compatible with old setup browser. + // Not use this field in new browser core. + // ErrorInfo = gFormData->ErrorString; } else { switch (gFormData->BrowserStatus) { @@ -3212,10 +3251,6 @@ BrowserStatusProcess ( ErrorInfo = gSaveFailed; break; - case BROWSER_NO_SUBMIT_IF: - ErrorInfo = gNoSubmitIf; - break; - case BROWSER_FORM_NOT_FOUND: ErrorInfo = gFormNotFound; break; @@ -3234,12 +3269,60 @@ BrowserStatusProcess ( } } - // - // Error occur, prompt error message. - // - do { - CreateDialog (&Key, gEmptyString, ErrorInfo, gPressEnter, gEmptyString, NULL); - } while (Key.UnicodeChar != CHAR_CARRIAGE_RETURN); + if (TimeOut == 0) { + do { + CreateDialog (&Key, gEmptyString, ErrorInfo, gPressEnter, gEmptyString, NULL); + } while (Key.UnicodeChar != CHAR_CARRIAGE_RETURN); + } else { + Status = gBS->CreateEvent (EVT_NOTIFY_WAIT, TPL_CALLBACK, EmptyEventProcess, NULL, &TimeOutEvent); + ASSERT_EFI_ERROR (Status); + + EventContext.SyncEvent = TimeOutEvent; + EventContext.TimeOut = &TimeOut; + EventContext.ErrorInfo = ErrorInfo; + + Status = gBS->CreateEvent (EVT_TIMER | EVT_NOTIFY_SIGNAL, TPL_CALLBACK, RefreshTimeOutProcess, &EventContext, &RefreshIntervalEvent); + ASSERT_EFI_ERROR (Status); + + // + // Show the dialog first to avoid long time not reaction. + // + gBS->SignalEvent (RefreshIntervalEvent); + + Status = gBS->SetTimer (RefreshIntervalEvent, TimerPeriodic, ONE_SECOND); + ASSERT_EFI_ERROR (Status); + + while (TRUE) { + Status = gST->ConIn->ReadKeyStroke (gST->ConIn, &Key); + if (!EFI_ERROR (Status) && Key.UnicodeChar == CHAR_CARRIAGE_RETURN) { + break; + } + + if (Status != EFI_NOT_READY) { + continue; + } + + WaitList[0] = TimeOutEvent; + WaitList[1] = gST->ConIn->WaitForKey; + + Status = gBS->WaitForEvent (2, WaitList, &Index); + ASSERT_EFI_ERROR (Status); + + if (Index == 0) { + // + // Timeout occur, close the hoot time out event. + // + break; + } + } + } + + gBS->CloseEvent (TimeOutEvent); + gBS->CloseEvent (RefreshIntervalEvent); + + if (StringToken != 0) { + FreePool (ErrorInfo); + } } /** diff --git a/MdeModulePkg/Universal/DisplayEngineDxe/FormDisplay.h b/MdeModulePkg/Universal/DisplayEngineDxe/FormDisplay.h index a0638caf5a..3f045cc323 100644 --- a/MdeModulePkg/Universal/DisplayEngineDxe/FormDisplay.h +++ b/MdeModulePkg/Universal/DisplayEngineDxe/FormDisplay.h @@ -201,6 +201,12 @@ typedef struct { UINT16 SkipValue; } DISPLAY_HIGHLIGHT_MENU_INFO; +typedef struct { + EFI_EVENT SyncEvent; + UINT8 *TimeOut; + CHAR16 *ErrorInfo; +} WARNING_IF_CONTEXT; + #define UI_MENU_OPTION_SIGNATURE SIGNATURE_32 ('u', 'i', 'm', 'm') typedef struct { @@ -576,17 +582,31 @@ ExitDisplay ( ); /** - Process validate for one question. + Process nothing. - @param Question The question which need to validate. - - @retval EFI_SUCCESS Question Option process success. - @retval Other Question Option process fail. + @param Event The Event need to be process + @param Context The context of the event. **/ -EFI_STATUS -ValidateQuestion ( - IN FORM_DISPLAY_ENGINE_STATEMENT *Question +VOID +EFIAPI +EmptyEventProcess ( + IN EFI_EVENT Event, + IN VOID *Context + ); + +/** + Process for the refresh interval statement. + + @param Event The Event need to be process + @param Context The context of the event. + +**/ +VOID +EFIAPI +RefreshTimeOutProcess ( + IN EFI_EVENT Event, + IN VOID *Context ); #endif diff --git a/MdeModulePkg/Universal/DisplayEngineDxe/InputHandler.c b/MdeModulePkg/Universal/DisplayEngineDxe/InputHandler.c index a58e12f12c..78dd10462c 100644 --- a/MdeModulePkg/Universal/DisplayEngineDxe/InputHandler.c +++ b/MdeModulePkg/Universal/DisplayEngineDxe/InputHandler.c @@ -872,7 +872,7 @@ EnterCarriageReturn: AdjustQuestionValue (QuestionValue, (UINT8)MenuOption->Sequence); } - return ValidateQuestion (Question); + return EFI_SUCCESS; break; case CHAR_BACKSPACE: @@ -1520,7 +1520,7 @@ TheKey: gST->ConOut->SetAttribute (gST->ConOut, SavedAttribute); - return ValidateQuestion (Question); + return EFI_SUCCESS; default: break; diff --git a/MdeModulePkg/Universal/DisplayEngineDxe/ProcessOptions.c b/MdeModulePkg/Universal/DisplayEngineDxe/ProcessOptions.c index 8da563ba70..1ab38b1df2 100644 --- a/MdeModulePkg/Universal/DisplayEngineDxe/ProcessOptions.c +++ b/MdeModulePkg/Universal/DisplayEngineDxe/ProcessOptions.c @@ -15,12 +15,6 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. #include "FormDisplay.h" -typedef struct { - EFI_EVENT SyncEvent; - UINT8 *TimeOut; - CHAR16 *ErrorInfo; -} WARNING_IF_CONTEXT; - #define MAX_TIME_OUT_LEN 0x10 /** @@ -667,143 +661,6 @@ RefreshTimeOutProcess ( *(EventInfo->TimeOut) -= 1; } -/** - Show the warning message. - - @param RetInfo The input warning string and timeout info. - -**/ -VOID -WarningIfCheck ( - IN STATEMENT_ERROR_INFO *RetInfo - ) -{ - CHAR16 *ErrorInfo; - EFI_EVENT WaitList[2]; - EFI_EVENT RefreshIntervalEvent; - EFI_EVENT TimeOutEvent; - UINT8 TimeOut; - EFI_STATUS Status; - UINTN Index; - WARNING_IF_CONTEXT EventContext; - EFI_INPUT_KEY Key; - - TimeOutEvent = NULL; - RefreshIntervalEvent = NULL; - - ASSERT (RetInfo->StringId != 0); - ErrorInfo = GetToken (RetInfo->StringId, gFormData->HiiHandle); - TimeOut = RetInfo->TimeOut; - if (RetInfo->TimeOut == 0) { - do { - CreateDialog (&Key, gEmptyString, ErrorInfo, gPressEnter, gEmptyString, NULL); - } while (Key.UnicodeChar != CHAR_CARRIAGE_RETURN); - } else { - Status = gBS->CreateEvent (EVT_NOTIFY_WAIT, TPL_CALLBACK, EmptyEventProcess, NULL, &TimeOutEvent); - ASSERT_EFI_ERROR (Status); - - EventContext.SyncEvent = TimeOutEvent; - EventContext.TimeOut = &TimeOut; - EventContext.ErrorInfo = ErrorInfo; - - Status = gBS->CreateEvent (EVT_TIMER | EVT_NOTIFY_SIGNAL, TPL_CALLBACK, RefreshTimeOutProcess, &EventContext, &RefreshIntervalEvent); - ASSERT_EFI_ERROR (Status); - - // - // Show the dialog first to avoid long time not reaction. - // - gBS->SignalEvent (RefreshIntervalEvent); - - Status = gBS->SetTimer (RefreshIntervalEvent, TimerPeriodic, ONE_SECOND); - ASSERT_EFI_ERROR (Status); - - while (TRUE) { - Status = gST->ConIn->ReadKeyStroke (gST->ConIn, &Key); - if (!EFI_ERROR (Status) && Key.UnicodeChar == CHAR_CARRIAGE_RETURN) { - break; - } - - if (Status != EFI_NOT_READY) { - continue; - } - - WaitList[0] = TimeOutEvent; - WaitList[1] = gST->ConIn->WaitForKey; - - Status = gBS->WaitForEvent (2, WaitList, &Index); - ASSERT_EFI_ERROR (Status); - - if (Index == 0) { - // - // Timeout occur, close the hoot time out event. - // - break; - } - } - } - - gBS->CloseEvent (TimeOutEvent); - gBS->CloseEvent (RefreshIntervalEvent); - - FreePool (ErrorInfo); -} - -/** - Process validate for one question. - - @param Question The question need to be validate. - - @retval EFI_SUCCESS Question Option process success. - @retval EFI_INVALID_PARAMETER Question Option process fail. - -**/ -EFI_STATUS -ValidateQuestion ( - IN FORM_DISPLAY_ENGINE_STATEMENT *Question - ) -{ - CHAR16 *ErrorInfo; - EFI_INPUT_KEY Key; - EFI_STATUS Status; - STATEMENT_ERROR_INFO RetInfo; - UINT32 RetVal; - - if (Question->ValidateQuestion == NULL) { - return EFI_SUCCESS; - } - - Status = EFI_SUCCESS; - RetVal = Question->ValidateQuestion(gFormData, Question, &gUserInput->InputValue, &RetInfo); - - switch (RetVal) { - case INCOSISTENT_IF_TRUE: - // - // Condition meet, show up error message - // - ASSERT (RetInfo.StringId != 0); - ErrorInfo = GetToken (RetInfo.StringId, gFormData->HiiHandle); - do { - CreateDialog (&Key, gEmptyString, ErrorInfo, gPressEnter, gEmptyString, NULL); - } while (Key.UnicodeChar != CHAR_CARRIAGE_RETURN); - FreePool (ErrorInfo); - - Status = EFI_INVALID_PARAMETER; - break; - - case WARNING_IF_TRUE: - // - // Condition meet, show up warning message - // - WarningIfCheck (&RetInfo); - break; - - default: - break; - } - - return Status; -} - /** Display error message for invalid password. @@ -935,7 +792,7 @@ PasswordProcess ( gUserInput->InputValue.Value.string = HiiSetString(gFormData->HiiHandle, gUserInput->InputValue.Value.string, StringPtr, NULL); FreePool (StringPtr); - Status = ValidateQuestion (Question); + Status = EFI_SUCCESS; if (EFI_ERROR (Status)) { // @@ -1277,7 +1134,7 @@ ProcessOptions ( // // Perform inconsistent check // - return ValidateQuestion (Question); + return EFI_SUCCESS; } else { *OptionString = AllocateZeroPool (BufferSize); ASSERT (*OptionString); @@ -1397,7 +1254,7 @@ ProcessOptions ( gUserInput->InputValue.Type = Question->CurrentValue.Type; gUserInput->InputValue.Value.string = HiiSetString(gFormData->HiiHandle, gUserInput->InputValue.Value.string, StringPtr, NULL); FreePool (StringPtr); - return ValidateQuestion (Question); + return EFI_SUCCESS; } else { *OptionString = AllocateZeroPool (BufferSize); ASSERT (*OptionString); diff --git a/MdeModulePkg/Universal/SetupBrowserDxe/IfrParse.c b/MdeModulePkg/Universal/SetupBrowserDxe/IfrParse.c index 41f89ea7f6..b4f045df60 100644 --- a/MdeModulePkg/Universal/SetupBrowserDxe/IfrParse.c +++ b/MdeModulePkg/Universal/SetupBrowserDxe/IfrParse.c @@ -286,13 +286,15 @@ CreateQuestion ( Allocate a FORM_EXPRESSION node. @param Form The Form associated with this Expression + @param OpCode The binary opcode data. @return Pointer to a FORM_EXPRESSION data structure. **/ FORM_EXPRESSION * CreateExpression ( - IN OUT FORM_BROWSER_FORM *Form + IN OUT FORM_BROWSER_FORM *Form, + IN UINT8 *OpCode ) { FORM_EXPRESSION *Expression; @@ -301,6 +303,7 @@ CreateExpression ( ASSERT (Expression != NULL); Expression->Signature = FORM_EXPRESSION_SIGNATURE; InitializeListHead (&Expression->OpCodeListHead); + Expression->OpCode = (EFI_IFR_OP_HEADER *) OpCode; return Expression; } @@ -1466,7 +1469,7 @@ ParseOpCodes ( // Create sub expression nested in MAP opcode // if (CurrentExpression == NULL && MapScopeDepth > 0) { - CurrentExpression = CreateExpression (CurrentForm); + CurrentExpression = CreateExpression (CurrentForm, OpCodeData); ASSERT (MapExpressionList != NULL); InsertTailList (MapExpressionList, &CurrentExpression->Link); if (Scope == 0) { @@ -2048,7 +2051,7 @@ ParseOpCodes ( // // Create an Expression node // - CurrentExpression = CreateExpression (CurrentForm); + CurrentExpression = CreateExpression (CurrentForm, OpCodeData); CopyMem (&CurrentExpression->Error, &((EFI_IFR_INCONSISTENT_IF *) OpCodeData)->Error, sizeof (EFI_STRING_ID)); if (Operand == EFI_IFR_NO_SUBMIT_IF_OP) { @@ -2072,7 +2075,7 @@ ParseOpCodes ( // // Create an Expression node // - CurrentExpression = CreateExpression (CurrentForm); + CurrentExpression = CreateExpression (CurrentForm, OpCodeData); CopyMem (&CurrentExpression->Error, &((EFI_IFR_WARNING_IF *) OpCodeData)->Warning, sizeof (EFI_STRING_ID)); CurrentExpression->TimeOut = ((EFI_IFR_WARNING_IF *) OpCodeData)->TimeOut; CurrentExpression->Type = EFI_HII_EXPRESSION_WARNING_IF; @@ -2091,7 +2094,7 @@ ParseOpCodes ( // // Question and Option will appear in scope of this OpCode // - CurrentExpression = CreateExpression (CurrentForm); + CurrentExpression = CreateExpression (CurrentForm, OpCodeData); CurrentExpression->Type = EFI_HII_EXPRESSION_SUPPRESS_IF; if (CurrentForm == NULL) { @@ -2121,7 +2124,7 @@ ParseOpCodes ( // // Questions will appear in scope of this OpCode // - CurrentExpression = CreateExpression (CurrentForm); + CurrentExpression = CreateExpression (CurrentForm, OpCodeData); CurrentExpression->Type = EFI_HII_EXPRESSION_GRAY_OUT_IF; InsertTailList (&CurrentForm->ExpressionListHead, &CurrentExpression->Link); PushConditionalExpression(CurrentExpression, ExpressStatement); @@ -2169,7 +2172,7 @@ ParseOpCodes ( // Expression // case EFI_IFR_VALUE_OP: - CurrentExpression = CreateExpression (CurrentForm); + CurrentExpression = CreateExpression (CurrentForm, OpCodeData); CurrentExpression->Type = EFI_HII_EXPRESSION_VALUE; InsertTailList (&CurrentForm->ExpressionListHead, &CurrentExpression->Link); @@ -2201,7 +2204,7 @@ ParseOpCodes ( break; case EFI_IFR_RULE_OP: - CurrentExpression = CreateExpression (CurrentForm); + CurrentExpression = CreateExpression (CurrentForm, OpCodeData); CurrentExpression->Type = EFI_HII_EXPRESSION_RULE; CurrentExpression->RuleId = ((EFI_IFR_RULE *) OpCodeData)->RuleId; @@ -2217,7 +2220,7 @@ ParseOpCodes ( break; case EFI_IFR_READ_OP: - CurrentExpression = CreateExpression (CurrentForm); + CurrentExpression = CreateExpression (CurrentForm, OpCodeData); CurrentExpression->Type = EFI_HII_EXPRESSION_READ; InsertTailList (&CurrentForm->ExpressionListHead, &CurrentExpression->Link); @@ -2239,7 +2242,7 @@ ParseOpCodes ( break; case EFI_IFR_WRITE_OP: - CurrentExpression = CreateExpression (CurrentForm); + CurrentExpression = CreateExpression (CurrentForm, OpCodeData); CurrentExpression->Type = EFI_HII_EXPRESSION_WRITE; InsertTailList (&CurrentForm->ExpressionListHead, &CurrentExpression->Link); diff --git a/MdeModulePkg/Universal/SetupBrowserDxe/Presentation.c b/MdeModulePkg/Universal/SetupBrowserDxe/Presentation.c index 8f2816502f..bad8b7b122 100644 --- a/MdeModulePkg/Universal/SetupBrowserDxe/Presentation.c +++ b/MdeModulePkg/Universal/SetupBrowserDxe/Presentation.c @@ -21,8 +21,6 @@ EFI_GUID mCurrentFormSetGuid = {0, 0, 0, {0, 0, 0, 0, 0, 0, 0, 0}}; UINT16 mCurrentFormId = 0; EFI_EVENT mValueChangedEvent = NULL; LIST_ENTRY mRefreshEventList = INITIALIZE_LIST_HEAD_VARIABLE (mRefreshEventList); -UINT32 gBrowserStatus = BROWSER_SUCCESS; -CHAR16 *gErrorInfo; UINT16 mCurFakeQestId; FORM_DISPLAY_ENGINE_FORM gDisplayFormData; BOOLEAN mFinishRetrieveCall = FALSE; @@ -226,162 +224,6 @@ CreateRefreshEvent ( InsertTailList(&mRefreshEventList, &EventNode->Link); } -/** - Perform value check for a question. - - @param Question The question need to do check. - @param Type Condition type need to check. - @param ErrorInfo Return info about the error. - - @retval The check result. -**/ -UINT32 -ConditionCheck ( - IN FORM_BROWSER_STATEMENT *Question, - IN UINT8 Type, - OUT STATEMENT_ERROR_INFO *ErrorInfo - ) -{ - EFI_STATUS Status; - LIST_ENTRY *Link; - FORM_EXPRESSION *Expression; - LIST_ENTRY *ListHead; - UINT32 RetVal; - - RetVal = STATEMENT_VALID; - ListHead = NULL; - - switch (Type) { - case EFI_HII_EXPRESSION_INCONSISTENT_IF: - ListHead = &Question->InconsistentListHead; - break; - - case EFI_HII_EXPRESSION_WARNING_IF: - ListHead = &Question->WarningListHead; - break; - - default: - ASSERT (FALSE); - return RetVal; - } - - ASSERT (ListHead != NULL); - Link = GetFirstNode (ListHead); - while (!IsNull (ListHead, Link)) { - Expression = FORM_EXPRESSION_FROM_LINK (Link); - Link = GetNextNode (ListHead, Link); - - // - // Evaluate the expression - // - Status = EvaluateExpression (gCurrentSelection->FormSet, gCurrentSelection->Form, Expression); - if (EFI_ERROR (Status)) { - continue; - } - - if ((Expression->Result.Type == EFI_IFR_TYPE_BOOLEAN) && Expression->Result.Value.b) { - ErrorInfo->StringId = Expression->Error; - switch (Type) { - case EFI_HII_EXPRESSION_INCONSISTENT_IF: - ErrorInfo->TimeOut = 0; - RetVal = INCOSISTENT_IF_TRUE; - break; - - case EFI_HII_EXPRESSION_WARNING_IF: - ErrorInfo->TimeOut = Expression->TimeOut; - RetVal = WARNING_IF_TRUE; - break; - - default: - ASSERT (FALSE); - break; - } - break; - } - } - - return RetVal; -} - -/** - Perform value check for a question. - - @param Form Form where Statement is in. - @param Statement Value will check for it. - @param InputValue New value will be checked. - @param ErrorInfo Return the error info for this check. - - @retval TRUE Input Value is valid. - @retval FALSE Input Value is invalid. -**/ -UINT32 -EFIAPI -QuestionCheck ( - IN FORM_DISPLAY_ENGINE_FORM *Form, - IN FORM_DISPLAY_ENGINE_STATEMENT *Statement, - IN EFI_HII_VALUE *InputValue, - OUT STATEMENT_ERROR_INFO *ErrorInfo - ) -{ - FORM_BROWSER_STATEMENT *Question; - EFI_HII_VALUE BackUpValue; - UINT8 *BackUpBuffer; - UINT32 RetVal; - - BackUpBuffer = NULL; - RetVal = STATEMENT_VALID; - - ASSERT (Form != NULL && Statement != NULL && InputValue != NULL && ErrorInfo != NULL); - - Question = GetBrowserStatement(Statement); - ASSERT (Question != NULL); - - // - // Back up the quesion value. - // - switch (Question->Operand) { - case EFI_IFR_ORDERED_LIST_OP: - BackUpBuffer = AllocateCopyPool (Question->StorageWidth, Question->BufferValue); - ASSERT (BackUpBuffer != NULL); - CopyMem (Question->BufferValue, InputValue->Buffer, Question->StorageWidth); - break; - - default: - CopyMem (&BackUpValue, &Question->HiiValue, sizeof (EFI_HII_VALUE)); - CopyMem (&Question->HiiValue, InputValue, sizeof (EFI_HII_VALUE)); - break; - } - - // - // Do the inconsistentif check. - // - if (!IsListEmpty (&Question->InconsistentListHead)) { - RetVal = ConditionCheck(Question, EFI_HII_EXPRESSION_INCONSISTENT_IF, ErrorInfo); - } - - // - // Do the warningif check. - // - if (RetVal == STATEMENT_VALID && !IsListEmpty (&Question->WarningListHead)) { - RetVal = ConditionCheck(Question, EFI_HII_EXPRESSION_WARNING_IF, ErrorInfo); - } - - // - // Restore the quesion value. - // - switch (Question->Operand) { - case EFI_IFR_ORDERED_LIST_OP: - CopyMem (Question->BufferValue, BackUpBuffer, Question->StorageWidth); - break; - - default: - CopyMem (&Question->HiiValue, &BackUpValue, sizeof (EFI_HII_VALUE)); - break; - } - - return RetVal; -} - /** Initialize the Display statement structure data. @@ -491,13 +333,6 @@ InitializeDisplayStatement ( DisplayStatement->PasswordCheck = PasswordCheck; } - // - // Save the validate check question for later use. - // - if (!IsListEmpty (&Statement->InconsistentListHead) || !IsListEmpty (&Statement->WarningListHead)) { - DisplayStatement->ValidateQuestion = QuestionCheck; - } - // // If this statement is nest in the subtitle, insert to the host statement. // else insert to the form it belongs to. @@ -858,12 +693,6 @@ UpdateDisplayFormData ( gDisplayFormData.FormRefreshEvent = NULL; gDisplayFormData.HighLightedStatement = NULL; - gDisplayFormData.BrowserStatus = gBrowserStatus; - gDisplayFormData.ErrorString = gErrorInfo; - - gBrowserStatus = BROWSER_SUCCESS; - gErrorInfo = NULL; - UpdateDataChangedFlag (); AddStatementToDisplayForm (); @@ -1098,7 +927,7 @@ ProcessAction ( if ((Action & BROWSER_ACTION_SUBMIT) == BROWSER_ACTION_SUBMIT) { Status = SubmitForm (gCurrentSelection->FormSet, gCurrentSelection->Form, gBrowserSettingScope); if (EFI_ERROR (Status)) { - gBrowserStatus = BROWSER_SUBMIT_FAIL; + PopupErrorMessage(BROWSER_SUBMIT_FAIL, NULL, NULL); } } @@ -1474,7 +1303,7 @@ ProcessGotoOpCode ( // // Not found the EFI_DEVICE_PATH_FROM_TEXT_PROTOCOL protocol. // - gBrowserStatus = BROWSER_PROTOCOL_NOT_FOUND; + PopupErrorMessage(BROWSER_PROTOCOL_NOT_FOUND, NULL, NULL); FreePool (StringPtr); return Status; } @@ -1551,7 +1380,7 @@ ProcessGotoOpCode ( // // Form is suppressed. // - gBrowserStatus = BROWSER_FORM_SUPPRESS; + PopupErrorMessage(BROWSER_FORM_SUPPRESS, NULL, NULL); return EFI_SUCCESS; } } @@ -2163,10 +1992,27 @@ ProcessCallBackFunction ( &ActionRequest ); if (!EFI_ERROR (Status)) { + // + // Need to sync the value between Statement->HiiValue->Value and Statement->BufferValue + // + if (HiiValue->Type == EFI_IFR_TYPE_STRING) { + NewString = GetToken (Statement->HiiValue.Value.string, FormSet->HiiHandle); + ASSERT (NewString != NULL); + + ASSERT (StrLen (NewString) * sizeof (CHAR16) <= Statement->StorageWidth); + if (StrLen (NewString) * sizeof (CHAR16) <= Statement->StorageWidth) { + CopyMem (Statement->BufferValue, NewString, StrSize (NewString)); + } else { + CopyMem (Statement->BufferValue, NewString, Statement->StorageWidth); + } + FreePool (NewString); + } + // // Only for EFI_BROWSER_ACTION_CHANGED need to handle this ActionRequest. // - if (Action == EFI_BROWSER_ACTION_CHANGED) { + switch (Action) { + case EFI_BROWSER_ACTION_CHANGED: switch (ActionRequest) { case EFI_BROWSER_ACTION_REQUEST_RESET: DiscardFormIsRequired = TRUE; @@ -2209,30 +2055,32 @@ ProcessCallBackFunction ( default: break; } - } + break; - // - // Need to sync the value between Statement->HiiValue->Value and Statement->BufferValue - // - if (HiiValue->Type == EFI_IFR_TYPE_STRING) { - NewString = GetToken (Statement->HiiValue.Value.string, FormSet->HiiHandle); - ASSERT (NewString != NULL); - - ASSERT (StrLen (NewString) * sizeof (CHAR16) <= Statement->StorageWidth); - if (StrLen (NewString) * sizeof (CHAR16) <= Statement->StorageWidth) { - CopyMem (Statement->BufferValue, NewString, StrSize (NewString)); - } else { - CopyMem (Statement->BufferValue, NewString, Statement->StorageWidth); + case EFI_BROWSER_ACTION_CHANGING: + // + // Do the question validation. + // + Status = ValueChangedValidation (gCurrentSelection->FormSet, gCurrentSelection->Form, Statement); + if (!EFI_ERROR (Status)) { + // + // According the spec, return value from call back of "changing" and + // "retrieve" should update to the question's temp buffer. + // + SetQuestionValue(FormSet, Form, Statement, GetSetValueWithEditBuffer); } - FreePool (NewString); - } + break; - // - // According the spec, return value from call back of "changing" and - // "retrieve" should update to the question's temp buffer. - // - if (Action == EFI_BROWSER_ACTION_CHANGING || Action == EFI_BROWSER_ACTION_RETRIEVE) { + case EFI_BROWSER_ACTION_RETRIEVE: + // + // According the spec, return value from call back of "changing" and + // "retrieve" should update to the question's temp buffer. + // SetQuestionValue(FormSet, Form, Statement, GetSetValueWithEditBuffer); + break; + + default: + break; } } else { // @@ -2246,8 +2094,14 @@ ProcessCallBackFunction ( } else { CopyMem (&HiiValue->Value, &BackUpValue, sizeof (EFI_IFR_TYPE_VALUE)); } - - SetQuestionValue(FormSet, Form, Statement, GetSetValueWithEditBuffer); + + // + // Do the question validation. + // + Status = ValueChangedValidation (gCurrentSelection->FormSet, gCurrentSelection->Form, Statement); + if (!EFI_ERROR (Status)) { + SetQuestionValue(FormSet, Form, Statement, GetSetValueWithEditBuffer); + } } // @@ -2451,7 +2305,7 @@ SetupBrowser ( // // Form is suppressed. // - gBrowserStatus = BROWSER_FORM_SUPPRESS; + PopupErrorMessage(BROWSER_FORM_SUPPRESS, NULL, NULL); Status = EFI_NOT_FOUND; goto Done; } @@ -2570,12 +2424,18 @@ SetupBrowser ( if (!EFI_ERROR (Status) && Statement->Operand != EFI_IFR_REF_OP) { ProcessCallBackFunction(Selection, Selection->FormSet, Selection->Form, Statement, EFI_BROWSER_ACTION_CHANGED, FALSE); } - } else if (Statement->Operand != EFI_IFR_PASSWORD_OP) { - SetQuestionValue (gCurrentSelection->FormSet, gCurrentSelection->Form, Statement, GetSetValueWithEditBuffer); + } else { // - // Verify whether question value has checked, update the ValueChanged flag in Question. + // Do the question validation. // - IsQuestionValueChanged(gCurrentSelection->FormSet, gCurrentSelection->Form, Statement, GetSetValueWithBuffer); + Status = ValueChangedValidation (gCurrentSelection->FormSet, gCurrentSelection->Form, Statement); + if (!EFI_ERROR (Status) && (Statement->Operand != EFI_IFR_PASSWORD_OP)) { + SetQuestionValue (gCurrentSelection->FormSet, gCurrentSelection->Form, Statement, GetSetValueWithEditBuffer); + // + // Verify whether question value has checked, update the ValueChanged flag in Question. + // + IsQuestionValueChanged(gCurrentSelection->FormSet, gCurrentSelection->Form, Statement, GetSetValueWithBuffer); + } } // diff --git a/MdeModulePkg/Universal/SetupBrowserDxe/Setup.c b/MdeModulePkg/Universal/SetupBrowserDxe/Setup.c index 26cbd234c6..af52f57103 100644 --- a/MdeModulePkg/Universal/SetupBrowserDxe/Setup.c +++ b/MdeModulePkg/Universal/SetupBrowserDxe/Setup.c @@ -63,8 +63,6 @@ CHAR16 *mUnknownString = L"!"; EFI_GUID gZeroGuid = {0, 0, 0, {0, 0, 0, 0, 0, 0, 0, 0}}; -extern UINT32 gBrowserStatus; -extern CHAR16 *gErrorInfo; extern EFI_GUID mCurrentFormSetGuid; extern EFI_HII_HANDLE mCurrentHiiHandle; extern UINT16 mCurrentFormId; @@ -310,6 +308,49 @@ LoadAllHiiFormset ( mSystemLevelFormSet = OldFormset; } +/** + Pop up the error info. + + @param BrowserStatus The input browser status. + @param OpCode The opcode use to get the erro info and timeout value. + @param ErrorString Error string used by BROWSER_NO_SUBMIT_IF. + +**/ +VOID +PopupErrorMessage ( + IN UINT32 BrowserStatus, + IN EFI_IFR_OP_HEADER *OpCode, OPTIONAL + IN CHAR16 *ErrorString + ) +{ + FORM_DISPLAY_ENGINE_STATEMENT *Statement; + + Statement = NULL; + + if (OpCode != NULL) { + Statement = AllocateZeroPool (sizeof(FORM_DISPLAY_ENGINE_STATEMENT)); + ASSERT (Statement != NULL); + Statement->OpCode = OpCode; + gDisplayFormData.HighLightedStatement = Statement; + } + + // + // Used to compatible with old display engine. + // New display engine not use this field. + // + gDisplayFormData.ErrorString = ErrorString; + gDisplayFormData.BrowserStatus = BrowserStatus; + + mFormDisplay->FormDisplay (&gDisplayFormData, NULL); + + gDisplayFormData.BrowserStatus = BROWSER_SUCCESS; + gDisplayFormData.ErrorString = NULL; + + if (OpCode != NULL) { + FreePool (Statement); + } +} + /** This is the routine which an external caller uses to direct the browser where to obtain it's information. @@ -425,19 +466,6 @@ SendForm ( FreePool (Selection); } - // - // Still has error info, pop up a message. - // - if (gBrowserStatus != BROWSER_SUCCESS) { - gDisplayFormData.BrowserStatus = gBrowserStatus; - gDisplayFormData.ErrorString = gErrorInfo; - - gBrowserStatus = BROWSER_SUCCESS; - gErrorInfo = NULL; - - mFormDisplay->FormDisplay (&gDisplayFormData, NULL); - } - if (ActionRequest != NULL) { *ActionRequest = EFI_BROWSER_ACTION_REQUEST_NONE; if (gResetRequired) { @@ -1920,12 +1948,28 @@ ValidateQuestion ( EFI_STATUS Status; LIST_ENTRY *Link; LIST_ENTRY *ListHead; - EFI_STRING PopUp; FORM_EXPRESSION *Expression; + UINT32 BrowserStatus; + CHAR16 *ErrorStr; - if (Type == EFI_HII_EXPRESSION_NO_SUBMIT_IF) { + BrowserStatus = BROWSER_SUCCESS; + ErrorStr = NULL; + + switch (Type) { + case EFI_HII_EXPRESSION_INCONSISTENT_IF: + ListHead = &Question->InconsistentListHead; + break; + + case EFI_HII_EXPRESSION_WARNING_IF: + ListHead = &Question->WarningListHead; + break; + + case EFI_HII_EXPRESSION_NO_SUBMIT_IF: ListHead = &Question->NoSubmitListHead; - } else { + break; + + default: + ASSERT (FALSE); return EFI_UNSUPPORTED; } @@ -1942,18 +1986,42 @@ ValidateQuestion ( } if ((Expression->Result.Type == EFI_IFR_TYPE_BOOLEAN) && Expression->Result.Value.b) { - // - // Condition meet, show up error message - // - if (Expression->Error != 0) { - PopUp = GetToken (Expression->Error, FormSet->HiiHandle); - if (Type == EFI_HII_EXPRESSION_NO_SUBMIT_IF) { - gBrowserStatus = BROWSER_NO_SUBMIT_IF; - gErrorInfo = PopUp; + switch (Type) { + case EFI_HII_EXPRESSION_INCONSISTENT_IF: + BrowserStatus = BROWSER_INCONSISTENT_IF; + break; + + case EFI_HII_EXPRESSION_WARNING_IF: + BrowserStatus = BROWSER_WARNING_IF; + break; + + case EFI_HII_EXPRESSION_NO_SUBMIT_IF: + BrowserStatus = BROWSER_NO_SUBMIT_IF; + // + // This code only used to compatible with old display engine, + // New display engine will not use this field. + // + if (Expression->Error != 0) { + ErrorStr = GetToken (Expression->Error, FormSet->HiiHandle); } + break; + + default: + ASSERT (FALSE); + break; } - return EFI_NOT_READY; + PopupErrorMessage(BrowserStatus, Expression->OpCode, ErrorStr); + + if (ErrorStr != NULL) { + FreePool (ErrorStr); + } + + if (Type == EFI_HII_EXPRESSION_WARNING_IF) { + return EFI_SUCCESS; + } else { + return EFI_NOT_READY; + } } Link = GetNextNode (ListHead, Link); @@ -1962,6 +2030,50 @@ ValidateQuestion ( return EFI_SUCCESS; } +/** + Perform question check. + + If one question has more than one check, process form high priority to low. + Only one error info will be popup. + + @param FormSet FormSet data structure. + @param Form Form data structure. + @param Question The Question to be validated. + + @retval EFI_SUCCESS Form validation pass. + @retval other Form validation failed. + +**/ +EFI_STATUS +ValueChangedValidation ( + IN FORM_BROWSER_FORMSET *FormSet, + IN FORM_BROWSER_FORM *Form, + IN FORM_BROWSER_STATEMENT *Question + ) +{ + EFI_STATUS Status; + + Status = EFI_SUCCESS; + + // + // Do the inconsistentif check. + // + if (!IsListEmpty (&Question->InconsistentListHead)) { + Status = ValidateQuestion (FormSet, Form, Question, EFI_HII_EXPRESSION_INCONSISTENT_IF); + if (EFI_ERROR (Status)) { + return Status; + } + } + + // + // Do the warningif check. + // + if (!IsListEmpty (&Question->WarningListHead)) { + Status = ValidateQuestion (FormSet, Form, Question, EFI_HII_EXPRESSION_WARNING_IF); + } + + return Status; +} /** Perform NoSubmit check for each Form in FormSet. diff --git a/MdeModulePkg/Universal/SetupBrowserDxe/Setup.h b/MdeModulePkg/Universal/SetupBrowserDxe/Setup.h index 44094efb29..cb3cc320bc 100644 --- a/MdeModulePkg/Universal/SetupBrowserDxe/Setup.h +++ b/MdeModulePkg/Universal/SetupBrowserDxe/Setup.h @@ -227,6 +227,7 @@ typedef struct { EFI_HII_VALUE Result; // Expression evaluation result UINT8 TimeOut; // For EFI_IFR_WARNING_IF + EFI_IFR_OP_HEADER *OpCode; // Save the opcode buffer. LIST_ENTRY OpCodeListHead; // OpCodes consist of this expression (EXPRESSION_OPCODE) } FORM_EXPRESSION; @@ -1675,4 +1676,39 @@ ConfigRequestAdjust ( IN BOOLEAN RespString ); +/** + Perform question check. + + If one question has more than one check, process form high priority to low. + + @param FormSet FormSet data structure. + @param Form Form data structure. + @param Question The Question to be validated. + + @retval EFI_SUCCESS Form validation pass. + @retval other Form validation failed. + +**/ +EFI_STATUS +ValueChangedValidation ( + IN FORM_BROWSER_FORMSET *FormSet, + IN FORM_BROWSER_FORM *Form, + IN FORM_BROWSER_STATEMENT *Question + ); + +/** + Pop up the error info. + + @param BrowserStatus The input browser status. + @param OpCode The opcode use to get the erro info and timeout value. + @param ErrorString Error string used by BROWSER_NO_SUBMIT_IF. + +**/ +VOID +PopupErrorMessage ( + IN UINT32 BrowserStatus, + IN EFI_IFR_OP_HEADER *OpCode, OPTIONAL + IN CHAR16 *ErrorString + ); + #endif