Update question validation logic, move the check pointer from after user input to after finish call the CHANGING callback.

Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Eric Dong <eric.dong@intel.com>
Reviewed-by: Liming, Gao <liming.gao@intel.com>

git-svn-id: https://svn.code.sf.net/p/edk2/code/trunk/edk2@15468 6f19259b-4bc3-4df7-8a09-765794883524
This commit is contained in:
Eric Dong
2014-04-15 15:38:48 +00:00
committed by ydong10
parent 387208ab04
commit bfae1330cc
9 changed files with 381 additions and 408 deletions

View File

@ -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_NOT_FOUND BROWSER_ERROR | 0x03
#define BROWSER_FORM_SUPPRESS BROWSER_ERROR | 0x04 #define BROWSER_FORM_SUPPRESS BROWSER_ERROR | 0x04
#define BROWSER_PROTOCOL_NOT_FOUND BROWSER_ERROR | 0x05 #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_STATEMENT_VERSION_1 0x10000
#define FORM_DISPLAY_ENGINE_VERSION_1 0x10000 #define FORM_DISPLAY_ENGINE_VERSION_1 0x10000

View File

@ -3197,14 +3197,53 @@ BrowserStatusProcess (
VOID VOID
) )
{ {
CHAR16 *ErrorInfo; CHAR16 *ErrorInfo;
EFI_INPUT_KEY Key; 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) { if (gFormData->BrowserStatus == BROWSER_SUCCESS) {
return; 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; ErrorInfo = gFormData->ErrorString;
} else { } else {
switch (gFormData->BrowserStatus) { switch (gFormData->BrowserStatus) {
@ -3212,10 +3251,6 @@ BrowserStatusProcess (
ErrorInfo = gSaveFailed; ErrorInfo = gSaveFailed;
break; break;
case BROWSER_NO_SUBMIT_IF:
ErrorInfo = gNoSubmitIf;
break;
case BROWSER_FORM_NOT_FOUND: case BROWSER_FORM_NOT_FOUND:
ErrorInfo = gFormNotFound; ErrorInfo = gFormNotFound;
break; break;
@ -3234,12 +3269,60 @@ BrowserStatusProcess (
} }
} }
// if (TimeOut == 0) {
// Error occur, prompt error message. do {
// CreateDialog (&Key, gEmptyString, ErrorInfo, gPressEnter, gEmptyString, NULL);
do { } while (Key.UnicodeChar != CHAR_CARRIAGE_RETURN);
CreateDialog (&Key, gEmptyString, ErrorInfo, gPressEnter, gEmptyString, NULL); } else {
} while (Key.UnicodeChar != CHAR_CARRIAGE_RETURN); 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);
}
} }
/** /**

View File

@ -201,6 +201,12 @@ typedef struct {
UINT16 SkipValue; UINT16 SkipValue;
} DISPLAY_HIGHLIGHT_MENU_INFO; } 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') #define UI_MENU_OPTION_SIGNATURE SIGNATURE_32 ('u', 'i', 'm', 'm')
typedef struct { typedef struct {
@ -576,17 +582,31 @@ ExitDisplay (
); );
/** /**
Process validate for one question. Process nothing.
@param Question The question which need to validate. @param Event The Event need to be process
@param Context The context of the event.
@retval EFI_SUCCESS Question Option process success.
@retval Other Question Option process fail.
**/ **/
EFI_STATUS VOID
ValidateQuestion ( EFIAPI
IN FORM_DISPLAY_ENGINE_STATEMENT *Question 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 #endif

View File

@ -872,7 +872,7 @@ EnterCarriageReturn:
AdjustQuestionValue (QuestionValue, (UINT8)MenuOption->Sequence); AdjustQuestionValue (QuestionValue, (UINT8)MenuOption->Sequence);
} }
return ValidateQuestion (Question); return EFI_SUCCESS;
break; break;
case CHAR_BACKSPACE: case CHAR_BACKSPACE:
@ -1520,7 +1520,7 @@ TheKey:
gST->ConOut->SetAttribute (gST->ConOut, SavedAttribute); gST->ConOut->SetAttribute (gST->ConOut, SavedAttribute);
return ValidateQuestion (Question); return EFI_SUCCESS;
default: default:
break; break;

View File

@ -15,12 +15,6 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
#include "FormDisplay.h" #include "FormDisplay.h"
typedef struct {
EFI_EVENT SyncEvent;
UINT8 *TimeOut;
CHAR16 *ErrorInfo;
} WARNING_IF_CONTEXT;
#define MAX_TIME_OUT_LEN 0x10 #define MAX_TIME_OUT_LEN 0x10
/** /**
@ -667,143 +661,6 @@ RefreshTimeOutProcess (
*(EventInfo->TimeOut) -= 1; *(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. Display error message for invalid password.
@ -935,7 +792,7 @@ PasswordProcess (
gUserInput->InputValue.Value.string = HiiSetString(gFormData->HiiHandle, gUserInput->InputValue.Value.string, StringPtr, NULL); gUserInput->InputValue.Value.string = HiiSetString(gFormData->HiiHandle, gUserInput->InputValue.Value.string, StringPtr, NULL);
FreePool (StringPtr); FreePool (StringPtr);
Status = ValidateQuestion (Question); Status = EFI_SUCCESS;
if (EFI_ERROR (Status)) { if (EFI_ERROR (Status)) {
// //
@ -1277,7 +1134,7 @@ ProcessOptions (
// //
// Perform inconsistent check // Perform inconsistent check
// //
return ValidateQuestion (Question); return EFI_SUCCESS;
} else { } else {
*OptionString = AllocateZeroPool (BufferSize); *OptionString = AllocateZeroPool (BufferSize);
ASSERT (*OptionString); ASSERT (*OptionString);
@ -1397,7 +1254,7 @@ ProcessOptions (
gUserInput->InputValue.Type = Question->CurrentValue.Type; gUserInput->InputValue.Type = Question->CurrentValue.Type;
gUserInput->InputValue.Value.string = HiiSetString(gFormData->HiiHandle, gUserInput->InputValue.Value.string, StringPtr, NULL); gUserInput->InputValue.Value.string = HiiSetString(gFormData->HiiHandle, gUserInput->InputValue.Value.string, StringPtr, NULL);
FreePool (StringPtr); FreePool (StringPtr);
return ValidateQuestion (Question); return EFI_SUCCESS;
} else { } else {
*OptionString = AllocateZeroPool (BufferSize); *OptionString = AllocateZeroPool (BufferSize);
ASSERT (*OptionString); ASSERT (*OptionString);

View File

@ -286,13 +286,15 @@ CreateQuestion (
Allocate a FORM_EXPRESSION node. Allocate a FORM_EXPRESSION node.
@param Form The Form associated with this Expression @param Form The Form associated with this Expression
@param OpCode The binary opcode data.
@return Pointer to a FORM_EXPRESSION data structure. @return Pointer to a FORM_EXPRESSION data structure.
**/ **/
FORM_EXPRESSION * FORM_EXPRESSION *
CreateExpression ( CreateExpression (
IN OUT FORM_BROWSER_FORM *Form IN OUT FORM_BROWSER_FORM *Form,
IN UINT8 *OpCode
) )
{ {
FORM_EXPRESSION *Expression; FORM_EXPRESSION *Expression;
@ -301,6 +303,7 @@ CreateExpression (
ASSERT (Expression != NULL); ASSERT (Expression != NULL);
Expression->Signature = FORM_EXPRESSION_SIGNATURE; Expression->Signature = FORM_EXPRESSION_SIGNATURE;
InitializeListHead (&Expression->OpCodeListHead); InitializeListHead (&Expression->OpCodeListHead);
Expression->OpCode = (EFI_IFR_OP_HEADER *) OpCode;
return Expression; return Expression;
} }
@ -1466,7 +1469,7 @@ ParseOpCodes (
// Create sub expression nested in MAP opcode // Create sub expression nested in MAP opcode
// //
if (CurrentExpression == NULL && MapScopeDepth > 0) { if (CurrentExpression == NULL && MapScopeDepth > 0) {
CurrentExpression = CreateExpression (CurrentForm); CurrentExpression = CreateExpression (CurrentForm, OpCodeData);
ASSERT (MapExpressionList != NULL); ASSERT (MapExpressionList != NULL);
InsertTailList (MapExpressionList, &CurrentExpression->Link); InsertTailList (MapExpressionList, &CurrentExpression->Link);
if (Scope == 0) { if (Scope == 0) {
@ -2048,7 +2051,7 @@ ParseOpCodes (
// //
// Create an Expression node // Create an Expression node
// //
CurrentExpression = CreateExpression (CurrentForm); CurrentExpression = CreateExpression (CurrentForm, OpCodeData);
CopyMem (&CurrentExpression->Error, &((EFI_IFR_INCONSISTENT_IF *) OpCodeData)->Error, sizeof (EFI_STRING_ID)); CopyMem (&CurrentExpression->Error, &((EFI_IFR_INCONSISTENT_IF *) OpCodeData)->Error, sizeof (EFI_STRING_ID));
if (Operand == EFI_IFR_NO_SUBMIT_IF_OP) { if (Operand == EFI_IFR_NO_SUBMIT_IF_OP) {
@ -2072,7 +2075,7 @@ ParseOpCodes (
// //
// Create an Expression node // Create an Expression node
// //
CurrentExpression = CreateExpression (CurrentForm); CurrentExpression = CreateExpression (CurrentForm, OpCodeData);
CopyMem (&CurrentExpression->Error, &((EFI_IFR_WARNING_IF *) OpCodeData)->Warning, sizeof (EFI_STRING_ID)); CopyMem (&CurrentExpression->Error, &((EFI_IFR_WARNING_IF *) OpCodeData)->Warning, sizeof (EFI_STRING_ID));
CurrentExpression->TimeOut = ((EFI_IFR_WARNING_IF *) OpCodeData)->TimeOut; CurrentExpression->TimeOut = ((EFI_IFR_WARNING_IF *) OpCodeData)->TimeOut;
CurrentExpression->Type = EFI_HII_EXPRESSION_WARNING_IF; CurrentExpression->Type = EFI_HII_EXPRESSION_WARNING_IF;
@ -2091,7 +2094,7 @@ ParseOpCodes (
// //
// Question and Option will appear in scope of this OpCode // Question and Option will appear in scope of this OpCode
// //
CurrentExpression = CreateExpression (CurrentForm); CurrentExpression = CreateExpression (CurrentForm, OpCodeData);
CurrentExpression->Type = EFI_HII_EXPRESSION_SUPPRESS_IF; CurrentExpression->Type = EFI_HII_EXPRESSION_SUPPRESS_IF;
if (CurrentForm == NULL) { if (CurrentForm == NULL) {
@ -2121,7 +2124,7 @@ ParseOpCodes (
// //
// Questions will appear in scope of this OpCode // Questions will appear in scope of this OpCode
// //
CurrentExpression = CreateExpression (CurrentForm); CurrentExpression = CreateExpression (CurrentForm, OpCodeData);
CurrentExpression->Type = EFI_HII_EXPRESSION_GRAY_OUT_IF; CurrentExpression->Type = EFI_HII_EXPRESSION_GRAY_OUT_IF;
InsertTailList (&CurrentForm->ExpressionListHead, &CurrentExpression->Link); InsertTailList (&CurrentForm->ExpressionListHead, &CurrentExpression->Link);
PushConditionalExpression(CurrentExpression, ExpressStatement); PushConditionalExpression(CurrentExpression, ExpressStatement);
@ -2169,7 +2172,7 @@ ParseOpCodes (
// Expression // Expression
// //
case EFI_IFR_VALUE_OP: case EFI_IFR_VALUE_OP:
CurrentExpression = CreateExpression (CurrentForm); CurrentExpression = CreateExpression (CurrentForm, OpCodeData);
CurrentExpression->Type = EFI_HII_EXPRESSION_VALUE; CurrentExpression->Type = EFI_HII_EXPRESSION_VALUE;
InsertTailList (&CurrentForm->ExpressionListHead, &CurrentExpression->Link); InsertTailList (&CurrentForm->ExpressionListHead, &CurrentExpression->Link);
@ -2201,7 +2204,7 @@ ParseOpCodes (
break; break;
case EFI_IFR_RULE_OP: case EFI_IFR_RULE_OP:
CurrentExpression = CreateExpression (CurrentForm); CurrentExpression = CreateExpression (CurrentForm, OpCodeData);
CurrentExpression->Type = EFI_HII_EXPRESSION_RULE; CurrentExpression->Type = EFI_HII_EXPRESSION_RULE;
CurrentExpression->RuleId = ((EFI_IFR_RULE *) OpCodeData)->RuleId; CurrentExpression->RuleId = ((EFI_IFR_RULE *) OpCodeData)->RuleId;
@ -2217,7 +2220,7 @@ ParseOpCodes (
break; break;
case EFI_IFR_READ_OP: case EFI_IFR_READ_OP:
CurrentExpression = CreateExpression (CurrentForm); CurrentExpression = CreateExpression (CurrentForm, OpCodeData);
CurrentExpression->Type = EFI_HII_EXPRESSION_READ; CurrentExpression->Type = EFI_HII_EXPRESSION_READ;
InsertTailList (&CurrentForm->ExpressionListHead, &CurrentExpression->Link); InsertTailList (&CurrentForm->ExpressionListHead, &CurrentExpression->Link);
@ -2239,7 +2242,7 @@ ParseOpCodes (
break; break;
case EFI_IFR_WRITE_OP: case EFI_IFR_WRITE_OP:
CurrentExpression = CreateExpression (CurrentForm); CurrentExpression = CreateExpression (CurrentForm, OpCodeData);
CurrentExpression->Type = EFI_HII_EXPRESSION_WRITE; CurrentExpression->Type = EFI_HII_EXPRESSION_WRITE;
InsertTailList (&CurrentForm->ExpressionListHead, &CurrentExpression->Link); InsertTailList (&CurrentForm->ExpressionListHead, &CurrentExpression->Link);

View File

@ -21,8 +21,6 @@ EFI_GUID mCurrentFormSetGuid = {0, 0, 0, {0, 0, 0, 0, 0, 0, 0, 0}};
UINT16 mCurrentFormId = 0; UINT16 mCurrentFormId = 0;
EFI_EVENT mValueChangedEvent = NULL; EFI_EVENT mValueChangedEvent = NULL;
LIST_ENTRY mRefreshEventList = INITIALIZE_LIST_HEAD_VARIABLE (mRefreshEventList); LIST_ENTRY mRefreshEventList = INITIALIZE_LIST_HEAD_VARIABLE (mRefreshEventList);
UINT32 gBrowserStatus = BROWSER_SUCCESS;
CHAR16 *gErrorInfo;
UINT16 mCurFakeQestId; UINT16 mCurFakeQestId;
FORM_DISPLAY_ENGINE_FORM gDisplayFormData; FORM_DISPLAY_ENGINE_FORM gDisplayFormData;
BOOLEAN mFinishRetrieveCall = FALSE; BOOLEAN mFinishRetrieveCall = FALSE;
@ -226,162 +224,6 @@ CreateRefreshEvent (
InsertTailList(&mRefreshEventList, &EventNode->Link); 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. Initialize the Display statement structure data.
@ -491,13 +333,6 @@ InitializeDisplayStatement (
DisplayStatement->PasswordCheck = PasswordCheck; 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. // If this statement is nest in the subtitle, insert to the host statement.
// else insert to the form it belongs to. // else insert to the form it belongs to.
@ -858,12 +693,6 @@ UpdateDisplayFormData (
gDisplayFormData.FormRefreshEvent = NULL; gDisplayFormData.FormRefreshEvent = NULL;
gDisplayFormData.HighLightedStatement = NULL; gDisplayFormData.HighLightedStatement = NULL;
gDisplayFormData.BrowserStatus = gBrowserStatus;
gDisplayFormData.ErrorString = gErrorInfo;
gBrowserStatus = BROWSER_SUCCESS;
gErrorInfo = NULL;
UpdateDataChangedFlag (); UpdateDataChangedFlag ();
AddStatementToDisplayForm (); AddStatementToDisplayForm ();
@ -1098,7 +927,7 @@ ProcessAction (
if ((Action & BROWSER_ACTION_SUBMIT) == BROWSER_ACTION_SUBMIT) { if ((Action & BROWSER_ACTION_SUBMIT) == BROWSER_ACTION_SUBMIT) {
Status = SubmitForm (gCurrentSelection->FormSet, gCurrentSelection->Form, gBrowserSettingScope); Status = SubmitForm (gCurrentSelection->FormSet, gCurrentSelection->Form, gBrowserSettingScope);
if (EFI_ERROR (Status)) { 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. // Not found the EFI_DEVICE_PATH_FROM_TEXT_PROTOCOL protocol.
// //
gBrowserStatus = BROWSER_PROTOCOL_NOT_FOUND; PopupErrorMessage(BROWSER_PROTOCOL_NOT_FOUND, NULL, NULL);
FreePool (StringPtr); FreePool (StringPtr);
return Status; return Status;
} }
@ -1551,7 +1380,7 @@ ProcessGotoOpCode (
// //
// Form is suppressed. // Form is suppressed.
// //
gBrowserStatus = BROWSER_FORM_SUPPRESS; PopupErrorMessage(BROWSER_FORM_SUPPRESS, NULL, NULL);
return EFI_SUCCESS; return EFI_SUCCESS;
} }
} }
@ -2163,10 +1992,27 @@ ProcessCallBackFunction (
&ActionRequest &ActionRequest
); );
if (!EFI_ERROR (Status)) { 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. // 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) { switch (ActionRequest) {
case EFI_BROWSER_ACTION_REQUEST_RESET: case EFI_BROWSER_ACTION_REQUEST_RESET:
DiscardFormIsRequired = TRUE; DiscardFormIsRequired = TRUE;
@ -2209,30 +2055,32 @@ ProcessCallBackFunction (
default: default:
break; break;
} }
} break;
// case EFI_BROWSER_ACTION_CHANGING:
// Need to sync the value between Statement->HiiValue->Value and Statement->BufferValue //
// // Do the question validation.
if (HiiValue->Type == EFI_IFR_TYPE_STRING) { //
NewString = GetToken (Statement->HiiValue.Value.string, FormSet->HiiHandle); Status = ValueChangedValidation (gCurrentSelection->FormSet, gCurrentSelection->Form, Statement);
ASSERT (NewString != NULL); if (!EFI_ERROR (Status)) {
//
ASSERT (StrLen (NewString) * sizeof (CHAR16) <= Statement->StorageWidth); // According the spec, return value from call back of "changing" and
if (StrLen (NewString) * sizeof (CHAR16) <= Statement->StorageWidth) { // "retrieve" should update to the question's temp buffer.
CopyMem (Statement->BufferValue, NewString, StrSize (NewString)); //
} else { SetQuestionValue(FormSet, Form, Statement, GetSetValueWithEditBuffer);
CopyMem (Statement->BufferValue, NewString, Statement->StorageWidth);
} }
FreePool (NewString); break;
}
// 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. // 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) { //
SetQuestionValue(FormSet, Form, Statement, GetSetValueWithEditBuffer); SetQuestionValue(FormSet, Form, Statement, GetSetValueWithEditBuffer);
break;
default:
break;
} }
} else { } else {
// //
@ -2246,8 +2094,14 @@ ProcessCallBackFunction (
} else { } else {
CopyMem (&HiiValue->Value, &BackUpValue, sizeof (EFI_IFR_TYPE_VALUE)); 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. // Form is suppressed.
// //
gBrowserStatus = BROWSER_FORM_SUPPRESS; PopupErrorMessage(BROWSER_FORM_SUPPRESS, NULL, NULL);
Status = EFI_NOT_FOUND; Status = EFI_NOT_FOUND;
goto Done; goto Done;
} }
@ -2570,12 +2424,18 @@ SetupBrowser (
if (!EFI_ERROR (Status) && Statement->Operand != EFI_IFR_REF_OP) { if (!EFI_ERROR (Status) && Statement->Operand != EFI_IFR_REF_OP) {
ProcessCallBackFunction(Selection, Selection->FormSet, Selection->Form, Statement, EFI_BROWSER_ACTION_CHANGED, FALSE); ProcessCallBackFunction(Selection, Selection->FormSet, Selection->Form, Statement, EFI_BROWSER_ACTION_CHANGED, FALSE);
} }
} else if (Statement->Operand != EFI_IFR_PASSWORD_OP) { } else {
SetQuestionValue (gCurrentSelection->FormSet, gCurrentSelection->Form, Statement, GetSetValueWithEditBuffer);
// //
// 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);
}
} }
// //

View File

@ -63,8 +63,6 @@ CHAR16 *mUnknownString = L"!";
EFI_GUID gZeroGuid = {0, 0, 0, {0, 0, 0, 0, 0, 0, 0, 0}}; 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_GUID mCurrentFormSetGuid;
extern EFI_HII_HANDLE mCurrentHiiHandle; extern EFI_HII_HANDLE mCurrentHiiHandle;
extern UINT16 mCurrentFormId; extern UINT16 mCurrentFormId;
@ -310,6 +308,49 @@ LoadAllHiiFormset (
mSystemLevelFormSet = OldFormset; 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 This is the routine which an external caller uses to direct the browser
where to obtain it's information. where to obtain it's information.
@ -425,19 +466,6 @@ SendForm (
FreePool (Selection); 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) { if (ActionRequest != NULL) {
*ActionRequest = EFI_BROWSER_ACTION_REQUEST_NONE; *ActionRequest = EFI_BROWSER_ACTION_REQUEST_NONE;
if (gResetRequired) { if (gResetRequired) {
@ -1920,12 +1948,28 @@ ValidateQuestion (
EFI_STATUS Status; EFI_STATUS Status;
LIST_ENTRY *Link; LIST_ENTRY *Link;
LIST_ENTRY *ListHead; LIST_ENTRY *ListHead;
EFI_STRING PopUp;
FORM_EXPRESSION *Expression; 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; ListHead = &Question->NoSubmitListHead;
} else { break;
default:
ASSERT (FALSE);
return EFI_UNSUPPORTED; return EFI_UNSUPPORTED;
} }
@ -1942,18 +1986,42 @@ ValidateQuestion (
} }
if ((Expression->Result.Type == EFI_IFR_TYPE_BOOLEAN) && Expression->Result.Value.b) { if ((Expression->Result.Type == EFI_IFR_TYPE_BOOLEAN) && Expression->Result.Value.b) {
// switch (Type) {
// Condition meet, show up error message case EFI_HII_EXPRESSION_INCONSISTENT_IF:
// BrowserStatus = BROWSER_INCONSISTENT_IF;
if (Expression->Error != 0) { break;
PopUp = GetToken (Expression->Error, FormSet->HiiHandle);
if (Type == EFI_HII_EXPRESSION_NO_SUBMIT_IF) { case EFI_HII_EXPRESSION_WARNING_IF:
gBrowserStatus = BROWSER_NO_SUBMIT_IF; BrowserStatus = BROWSER_WARNING_IF;
gErrorInfo = PopUp; 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); Link = GetNextNode (ListHead, Link);
@ -1962,6 +2030,50 @@ ValidateQuestion (
return EFI_SUCCESS; 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. Perform NoSubmit check for each Form in FormSet.

View File

@ -227,6 +227,7 @@ typedef struct {
EFI_HII_VALUE Result; // Expression evaluation result EFI_HII_VALUE Result; // Expression evaluation result
UINT8 TimeOut; // For EFI_IFR_WARNING_IF 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) LIST_ENTRY OpCodeListHead; // OpCodes consist of this expression (EXPRESSION_OPCODE)
} FORM_EXPRESSION; } FORM_EXPRESSION;
@ -1675,4 +1676,39 @@ ConfigRequestAdjust (
IN BOOLEAN RespString 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 #endif