/** @file\r
Utility functions for UI presentation.\r
\r
-Copyright (c) 2004 - 2009, Intel Corporation\r
-All rights reserved. This program and the accompanying materials\r
+Copyright (c) 2004 - 2013, Intel Corporation. All rights reserved.<BR>\r
+This program and the accompanying materials\r
are licensed and made available under the terms and conditions of the BSD License\r
which accompanies this distribution. The full text of the license may be found at\r
http://opensource.org/licenses/bsd-license.php\r
**/\r
\r
#include "Setup.h"\r
-#include "Ui.h"\r
\r
BOOLEAN mHiiPackageListUpdated;\r
UI_MENU_SELECTION *gCurrentSelection;\r
+EFI_HII_HANDLE mCurrentHiiHandle = NULL;\r
+EFI_GUID mCurrentFormSetGuid = {0, 0, 0, {0, 0, 0, 0, 0, 0, 0, 0}};\r
+UINT16 mCurrentFormId = 0;\r
+EFI_EVENT mValueChangedEvent = NULL;\r
+LIST_ENTRY mRefreshEventList = INITIALIZE_LIST_HEAD_VARIABLE (mRefreshEventList);\r
+UINT32 gBrowserStatus = BROWSER_SUCCESS;\r
+CHAR16 *gErrorInfo;\r
+UINT16 mCurFakeQestId;\r
+FORM_DISPLAY_ENGINE_FORM gDisplayFormData;\r
\r
+/**\r
+ Evaluate all expressions in a Form.\r
+\r
+ @param FormSet FormSet this Form belongs to.\r
+ @param Form The Form.\r
+\r
+ @retval EFI_SUCCESS The expression evaluated successfuly\r
+\r
+**/\r
+EFI_STATUS\r
+EvaluateFormExpressions (\r
+ IN FORM_BROWSER_FORMSET *FormSet,\r
+ IN FORM_BROWSER_FORM *Form\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ LIST_ENTRY *Link;\r
+ FORM_EXPRESSION *Expression;\r
+\r
+ Link = GetFirstNode (&Form->ExpressionListHead);\r
+ while (!IsNull (&Form->ExpressionListHead, Link)) {\r
+ Expression = FORM_EXPRESSION_FROM_LINK (Link);\r
+ Link = GetNextNode (&Form->ExpressionListHead, Link);\r
+\r
+ if (Expression->Type == EFI_HII_EXPRESSION_INCONSISTENT_IF ||\r
+ Expression->Type == EFI_HII_EXPRESSION_NO_SUBMIT_IF ||\r
+ Expression->Type == EFI_HII_EXPRESSION_WRITE ||\r
+ (Expression->Type == EFI_HII_EXPRESSION_READ && Form->FormType != STANDARD_MAP_FORM_TYPE)) {\r
+ //\r
+ // Postpone Form validation to Question editing or Form submitting or Question Write or Question Read for nonstandard form.\r
+ //\r
+ continue;\r
+ }\r
+\r
+ Status = EvaluateExpression (FormSet, Form, Expression);\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+ }\r
+\r
+ return EFI_SUCCESS;\r
+}\r
\r
/**\r
- Clear retangle with specified text attribute.\r
+ Add empty function for event process function.\r
\r
- @param LeftColumn Left column of retangle.\r
- @param RightColumn Right column of retangle.\r
- @param TopRow Start row of retangle.\r
- @param BottomRow End row of retangle.\r
- @param TextAttribute The character foreground and background.\r
+ @param Event The Event need to be process\r
+ @param Context The context of the event.\r
\r
**/\r
VOID\r
-ClearLines (\r
- IN UINTN LeftColumn,\r
- IN UINTN RightColumn,\r
- IN UINTN TopRow,\r
- IN UINTN BottomRow,\r
- IN UINTN TextAttribute\r
+EFIAPI\r
+SetupBrowserEmptyFunction (\r
+ IN EFI_EVENT Event,\r
+ IN VOID *Context\r
)\r
{\r
- CHAR16 *Buffer;\r
- UINTN Row;\r
+}\r
\r
- //\r
- // For now, allocate an arbitrarily long buffer\r
- //\r
- Buffer = AllocateZeroPool (0x10000);\r
- ASSERT (Buffer != NULL);\r
+/**\r
+ Base on the opcode buffer info to get the display statement.\r
\r
- //\r
- // Set foreground and background as defined\r
- //\r
- gST->ConOut->SetAttribute (gST->ConOut, TextAttribute);\r
+ @param OpCode The input opcode buffer for this statement.\r
+ \r
+ @retval Statement The statement use this opcode buffer.\r
\r
- //\r
- // Much faster to buffer the long string instead of print it a character at a time\r
- //\r
- SetUnicodeMem (Buffer, RightColumn - LeftColumn, L' ');\r
+**/\r
+FORM_DISPLAY_ENGINE_STATEMENT *\r
+GetDisplayStatement (\r
+ IN EFI_IFR_OP_HEADER *OpCode\r
+ )\r
+{\r
+ FORM_DISPLAY_ENGINE_STATEMENT *DisplayStatement;\r
+ LIST_ENTRY *Link;\r
\r
- //\r
- // Clear the desired area with the appropriate foreground/background\r
- //\r
- for (Row = TopRow; Row <= BottomRow; Row++) {\r
- PrintStringAt (LeftColumn, Row, Buffer);\r
+ Link = GetFirstNode (&gDisplayFormData.StatementListHead);\r
+ while (!IsNull (&gDisplayFormData.StatementListHead, Link)) {\r
+ DisplayStatement = FORM_DISPLAY_ENGINE_STATEMENT_FROM_LINK (Link);\r
+\r
+ if (DisplayStatement->OpCode == OpCode) {\r
+ return DisplayStatement;\r
+ }\r
+ Link = GetNextNode (&gDisplayFormData.StatementListHead, Link);\r
}\r
\r
- gST->ConOut->SetCursorPosition (gST->ConOut, LeftColumn, TopRow);\r
+ return NULL;\r
+}\r
+\r
+/**\r
+ Free the refresh event list.\r
+\r
+**/\r
+VOID \r
+FreeRefreshEvent (\r
+ VOID\r
+ )\r
+{\r
+ LIST_ENTRY *Link;\r
+ FORM_BROWSER_REFRESH_EVENT_NODE *EventNode;\r
+\r
+ while (!IsListEmpty (&mRefreshEventList)) {\r
+ Link = GetFirstNode (&mRefreshEventList);\r
+ EventNode = FORM_BROWSER_REFRESH_EVENT_FROM_LINK (Link);\r
+ RemoveEntryList (&EventNode->Link);\r
+\r
+ gBS->CloseEvent (EventNode->RefreshEvent);\r
\r
- FreePool (Buffer);\r
- return ;\r
+ FreePool (EventNode);\r
+ }\r
}\r
\r
/**\r
- Concatenate a narrow string to another string.\r
+ Check whether this statement value is changed. If yes, update the statement value and return TRUE; \r
+ else return FALSE.\r
\r
- @param Destination The destination string.\r
- @param Source The source string. The string to be concatenated.\r
- to the end of Destination.\r
+ @param Statement The statement need to check.\r
\r
**/\r
VOID\r
-NewStrCat (\r
- IN OUT CHAR16 *Destination,\r
- IN CHAR16 *Source\r
+UpdateStatement (\r
+ IN OUT FORM_BROWSER_STATEMENT *Statement\r
)\r
{\r
- UINTN Length;\r
+ GetQuestionValue (gCurrentSelection->FormSet, gCurrentSelection->Form, Statement, GetSetValueWithHiiDriver);\r
\r
- for (Length = 0; Destination[Length] != 0; Length++)\r
- ;\r
+ //\r
+ // Reset FormPackage update flag\r
+ //\r
+ mHiiPackageListUpdated = FALSE;\r
\r
//\r
- // We now have the length of the original string\r
- // We can safely assume for now that we are concatenating a narrow value to this string.\r
- // For instance, the string is "XYZ" and cat'ing ">"\r
- // If this assumption changes, we need to make this routine a bit more complex\r
+ // Question value may be changed, need invoke its Callback()\r
//\r
- Destination[Length] = NARROW_CHAR;\r
- Length++;\r
+ ProcessCallBackFunction (gCurrentSelection, Statement, EFI_BROWSER_ACTION_CHANGING, FALSE);\r
+ \r
+ if (mHiiPackageListUpdated) {\r
+ //\r
+ // Package list is updated, force to reparse IFR binary of target Formset\r
+ //\r
+ mHiiPackageListUpdated = FALSE;\r
+ gCurrentSelection->Action = UI_ACTION_REFRESH_FORMSET;\r
+ }\r
+}\r
\r
- StrCpy (Destination + Length, Source);\r
+/**\r
+ Refresh the question which has refresh guid event attribute.\r
+ \r
+ @param Event The event which has this function related. \r
+ @param Context The input context info related to this event or the status code return to the caller.\r
+**/\r
+VOID\r
+EFIAPI\r
+RefreshEventNotify(\r
+ IN EFI_EVENT Event,\r
+ IN VOID *Context\r
+ )\r
+{\r
+ FORM_BROWSER_STATEMENT *Statement;\r
+\r
+ Statement = (FORM_BROWSER_STATEMENT *)Context;\r
+ UpdateStatement(Statement);\r
+ gBS->SignalEvent (mValueChangedEvent);\r
}\r
\r
+\r
/**\r
- Count the storage space of a Unicode string.\r
+ Create refresh hook event for statement which has refresh event or interval.\r
\r
- This function handles the Unicode string with NARROW_CHAR\r
- and WIDE_CHAR control characters. NARROW_HCAR and WIDE_CHAR\r
- does not count in the resultant output. If a WIDE_CHAR is\r
- hit, then 2 Unicode character will consume an output storage\r
- space with size of CHAR16 till a NARROW_CHAR is hit.\r
+ @param Statement The statement need to check.\r
\r
- @param String The input string to be counted.\r
+**/\r
+VOID\r
+CreateRefreshEvent (\r
+ IN FORM_BROWSER_STATEMENT *Statement\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ EFI_EVENT RefreshEvent;\r
+ FORM_BROWSER_REFRESH_EVENT_NODE *EventNode;\r
\r
- @return Storage space for the input string.\r
+ //\r
+ // If question has refresh guid, create the notify function.\r
+ //\r
+ Status = gBS->CreateEventEx (\r
+ EVT_NOTIFY_SIGNAL,\r
+ TPL_CALLBACK,\r
+ RefreshEventNotify,\r
+ Statement,\r
+ &Statement->RefreshGuid,\r
+ &RefreshEvent);\r
+ ASSERT_EFI_ERROR (Status);\r
+\r
+ EventNode = AllocateZeroPool (sizeof (FORM_BROWSER_REFRESH_EVENT_NODE));\r
+ ASSERT (EventNode != NULL);\r
+ EventNode->RefreshEvent = RefreshEvent;\r
+ InsertTailList(&mRefreshEventList, &EventNode->Link);\r
+}\r
\r
+/**\r
+ Perform value check for a question.\r
+ \r
+ @param Question The question need to do check.\r
+ @param ErrorInfo Return info about the error.\r
+ \r
+ @retval The check result.\r
**/\r
-UINTN\r
-GetStringWidth (\r
- IN CHAR16 *String\r
+UINT32\r
+InConsistentIfCheck (\r
+ IN FORM_BROWSER_STATEMENT *Question,\r
+ OUT STATEMENT_ERROR_INFO *ErrorInfo\r
)\r
{\r
- UINTN Index;\r
- UINTN Count;\r
- UINTN IncrementValue;\r
+ EFI_STATUS Status;\r
+ LIST_ENTRY *Link;\r
+ FORM_EXPRESSION *Expression;\r
+ LIST_ENTRY *ListHead;\r
+ UINT32 RetVal;\r
\r
- Index = 0;\r
- Count = 0;\r
- IncrementValue = 1;\r
+ RetVal = STATEMENT_VALID;\r
+ ListHead = &Question->InconsistentListHead;\r
\r
- do {\r
- //\r
- // Advance to the null-terminator or to the first width directive\r
- //\r
- for (;\r
- (String[Index] != NARROW_CHAR) && (String[Index] != WIDE_CHAR) && (String[Index] != 0);\r
- Index++, Count = Count + IncrementValue\r
- )\r
- ;\r
+ Link = GetFirstNode (ListHead);\r
+ while (!IsNull (ListHead, Link)) {\r
+ Expression = FORM_EXPRESSION_FROM_LINK (Link);\r
+ Link = GetNextNode (ListHead, Link);\r
\r
//\r
- // We hit the null-terminator, we now have a count\r
- //\r
- if (String[Index] == 0) {\r
- break;\r
- }\r
- //\r
- // We encountered a narrow directive - strip it from the size calculation since it doesn't get printed\r
- // and also set the flag that determines what we increment by.(if narrow, increment by 1, if wide increment by 2)\r
+ // Evaluate the expression\r
//\r
- if (String[Index] == NARROW_CHAR) {\r
- //\r
- // Skip to the next character\r
- //\r
- Index++;\r
- IncrementValue = 1;\r
- } else {\r
- //\r
- // Skip to the next character\r
- //\r
- Index++;\r
- IncrementValue = 2;\r
+ Status = EvaluateExpression (gCurrentSelection->FormSet, gCurrentSelection->Form, Expression);\r
+ if (EFI_ERROR (Status)) {\r
+ continue;\r
}\r
- } while (String[Index] != 0);\r
\r
- //\r
- // Increment by one to include the null-terminator in the size\r
- //\r
- Count++;\r
+ if ((Expression->Result.Type == EFI_IFR_TYPE_BOOLEAN) && Expression->Result.Value.b) {\r
+ ErrorInfo->StringId = Expression->Error;\r
+ ErrorInfo->TimeOut = 0;\r
+ RetVal = INCOSISTENT_IF_TRUE;\r
+ break;\r
+ }\r
+ }\r
\r
- return Count * sizeof (CHAR16);\r
+ return RetVal;\r
}\r
\r
/**\r
- This function displays the page frame.\r
-\r
+ Perform value check for a question.\r
+ \r
+ @param Form Form where Statement is in.\r
+ @param Statement Value will check for it.\r
+ @param InputValue New value will be checked.\r
+ @param ErrorInfo Return the error info for this check.\r
+ \r
+ @retval TRUE Input Value is valid.\r
+ @retval FALSE Input Value is invalid.\r
**/\r
-VOID\r
-DisplayPageFrame (\r
- VOID\r
+UINT32\r
+EFIAPI\r
+QuestionCheck (\r
+ IN FORM_DISPLAY_ENGINE_FORM *Form,\r
+ IN FORM_DISPLAY_ENGINE_STATEMENT *Statement,\r
+ IN EFI_HII_VALUE *InputValue,\r
+ OUT STATEMENT_ERROR_INFO *ErrorInfo\r
)\r
{\r
- UINTN Index;\r
- UINT8 Line;\r
- UINT8 Alignment;\r
- CHAR16 Character;\r
- CHAR16 *Buffer;\r
- CHAR16 *StrFrontPageBanner;\r
- UINTN Row;\r
- EFI_SCREEN_DESCRIPTOR LocalScreen;\r
- UINT8 RowIdx;\r
- UINT8 ColumnIdx;\r
+ FORM_BROWSER_STATEMENT *Question;\r
+ EFI_HII_VALUE BackUpValue;\r
+ UINT8 *BackUpBuffer;\r
+ UINT32 RetVal;\r
+\r
+ BackUpBuffer = NULL;\r
+ RetVal = STATEMENT_VALID;\r
\r
- ZeroMem (&LocalScreen, sizeof (EFI_SCREEN_DESCRIPTOR));\r
- gST->ConOut->QueryMode (gST->ConOut, gST->ConOut->Mode->Mode, &LocalScreen.RightColumn, &LocalScreen.BottomRow);\r
- ClearLines (0, LocalScreen.RightColumn, 0, LocalScreen.BottomRow, KEYHELP_BACKGROUND);\r
+ ASSERT (Form != NULL && Statement != NULL && InputValue != NULL && ErrorInfo != NULL);\r
\r
- CopyMem (&LocalScreen, &gScreenDimensions, sizeof (EFI_SCREEN_DESCRIPTOR));\r
+ Question = GetBrowserStatement(Statement);\r
+ ASSERT (Question != NULL);\r
\r
//\r
- // For now, allocate an arbitrarily long buffer\r
+ // Back up the quesion value.\r
//\r
- Buffer = AllocateZeroPool (0x10000);\r
- ASSERT (Buffer != NULL);\r
+ switch (Question->Operand) {\r
+ case EFI_IFR_ORDERED_LIST_OP:\r
+ BackUpBuffer = AllocateCopyPool (Question->StorageWidth, Question->BufferValue);\r
+ ASSERT (BackUpBuffer != NULL);\r
+ CopyMem (Question->BufferValue, InputValue->Buffer, Question->StorageWidth);\r
+ break;\r
\r
- Character = BOXDRAW_HORIZONTAL;\r
+ default:\r
+ CopyMem (&BackUpValue, &Question->HiiValue, sizeof (EFI_HII_VALUE));\r
+ CopyMem (&Question->HiiValue, InputValue, sizeof (EFI_HII_VALUE));\r
+ break;\r
+ }\r
\r
- for (Index = 0; Index + 2 < (LocalScreen.RightColumn - LocalScreen.LeftColumn); Index++) {\r
- Buffer[Index] = Character;\r
+ //\r
+ // Do the inconsistentif check.\r
+ //\r
+ if (!IsListEmpty (&Question->InconsistentListHead)) {\r
+ RetVal = InConsistentIfCheck(Question, ErrorInfo);\r
}\r
\r
- if (gClassOfVfr == FORMSET_CLASS_FRONT_PAGE) {\r
- //\r
- // ClearLines(0, LocalScreen.RightColumn, 0, BANNER_HEIGHT-1, BANNER_TEXT | BANNER_BACKGROUND);\r
- //\r
- ClearLines (\r
- LocalScreen.LeftColumn,\r
- LocalScreen.RightColumn,\r
- LocalScreen.TopRow,\r
- FRONT_PAGE_HEADER_HEIGHT - 1 + LocalScreen.TopRow,\r
- BANNER_TEXT | BANNER_BACKGROUND\r
- );\r
- //\r
- // for (Line = 0; Line < BANNER_HEIGHT; Line++) {\r
- //\r
- for (Line = (UINT8) LocalScreen.TopRow; Line < BANNER_HEIGHT + (UINT8) LocalScreen.TopRow; Line++) {\r
- //\r
- // for (Alignment = 0; Alignment < BANNER_COLUMNS; Alignment++) {\r
- //\r
- for (Alignment = (UINT8) LocalScreen.LeftColumn;\r
- Alignment < BANNER_COLUMNS + (UINT8) LocalScreen.LeftColumn;\r
- Alignment++\r
- ) {\r
- RowIdx = (UINT8) (Line - (UINT8) LocalScreen.TopRow);\r
- ColumnIdx = (UINT8) (Alignment - (UINT8) LocalScreen.LeftColumn);\r
-\r
- ASSERT (RowIdx < BANNER_HEIGHT);\r
- ASSERT (ColumnIdx < BANNER_COLUMNS);\r
-\r
- if (gBannerData->Banner[RowIdx][ColumnIdx] != 0x0000) {\r
- StrFrontPageBanner = GetToken (\r
- gBannerData->Banner[RowIdx][ColumnIdx],\r
- gFrontPageHandle\r
- );\r
- } else {\r
- continue;\r
- }\r
+ //\r
+ // Restore the quesion value.\r
+ //\r
+ switch (Question->Operand) {\r
+ case EFI_IFR_ORDERED_LIST_OP:\r
+ CopyMem (Question->BufferValue, BackUpBuffer, Question->StorageWidth);\r
+ break;\r
\r
- switch (Alignment - LocalScreen.LeftColumn) {\r
- case 0:\r
- //\r
- // Handle left column\r
- //\r
- PrintStringAt (LocalScreen.LeftColumn, Line, StrFrontPageBanner);\r
- break;\r
+ default:\r
+ CopyMem (&Question->HiiValue, &BackUpValue, sizeof (EFI_HII_VALUE));\r
+ break;\r
+ }\r
\r
- case 1:\r
- //\r
- // Handle center column\r
- //\r
- PrintStringAt (\r
- LocalScreen.LeftColumn + (LocalScreen.RightColumn - LocalScreen.LeftColumn) / 3,\r
- Line,\r
- StrFrontPageBanner\r
- );\r
- break;\r
+ return RetVal;\r
+}\r
\r
- case 2:\r
- //\r
- // Handle right column\r
- //\r
- PrintStringAt (\r
- LocalScreen.LeftColumn + (LocalScreen.RightColumn - LocalScreen.LeftColumn) * 2 / 3,\r
- Line,\r
- StrFrontPageBanner\r
- );\r
- break;\r
- }\r
+/**\r
\r
- FreePool (StrFrontPageBanner);\r
- }\r
+ Initialize the Display statement structure data.\r
+\r
+ @param DisplayStatement Pointer to the display Statement data strucure.\r
+ @param Statement The statement need to check.\r
+ @param HostDisplayStatement Pointer to the display Statement data strucure which is an host statement.\r
+**/\r
+VOID\r
+InitializeDisplayStatement (\r
+ IN OUT FORM_DISPLAY_ENGINE_STATEMENT *DisplayStatement,\r
+ IN FORM_BROWSER_STATEMENT *Statement,\r
+ IN FORM_DISPLAY_ENGINE_STATEMENT *HostDisplayStatement\r
+ )\r
+{\r
+ LIST_ENTRY *Link;\r
+ QUESTION_OPTION *Option;\r
+ DISPLAY_QUESTION_OPTION *DisplayOption;\r
+\r
+ DisplayStatement->Signature = FORM_DISPLAY_ENGINE_STATEMENT_SIGNATURE;\r
+ DisplayStatement->Version = FORM_DISPLAY_ENGINE_STATEMENT_VERSION_1;\r
+ DisplayStatement->OpCode = Statement->OpCode;\r
+ InitializeListHead (&DisplayStatement->NestStatementList);\r
+ InitializeListHead (&DisplayStatement->OptionListHead);\r
+\r
+ if ((EvaluateExpressionList(Statement->Expression, FALSE, NULL, NULL) == ExpressGrayOut) || Statement->Locked) {\r
+ DisplayStatement->Attribute |= HII_DISPLAY_GRAYOUT;\r
+ }\r
+ if ((Statement->ValueExpression != NULL) || ((Statement->QuestionFlags & EFI_IFR_FLAG_READ_ONLY) != 0)) {\r
+ DisplayStatement->Attribute |= HII_DISPLAY_READONLY;\r
+ }\r
+\r
+ //\r
+ // Initilize the option list in statement.\r
+ //\r
+ Link = GetFirstNode (&Statement->OptionListHead);\r
+ while (!IsNull (&Statement->OptionListHead, Link)) {\r
+ Option = QUESTION_OPTION_FROM_LINK (Link);\r
+ Link = GetNextNode (&Statement->OptionListHead, Link);\r
+ if ((Option->SuppressExpression != NULL) &&\r
+ ((EvaluateExpressionList(Option->SuppressExpression, FALSE, NULL, NULL) == ExpressSuppress))) {\r
+ continue;\r
}\r
+\r
+ DisplayOption = AllocateZeroPool (sizeof (DISPLAY_QUESTION_OPTION));\r
+ ASSERT (DisplayOption != NULL);\r
+\r
+ DisplayOption->ImageId = Option->ImageId;\r
+ DisplayOption->Signature = DISPLAY_QUESTION_OPTION_SIGNATURE;\r
+ DisplayOption->OptionOpCode = Option->OpCode;\r
+ InsertTailList(&DisplayStatement->OptionListHead, &DisplayOption->Link);\r
}\r
\r
- ClearLines (\r
- LocalScreen.LeftColumn,\r
- LocalScreen.RightColumn,\r
- LocalScreen.BottomRow - STATUS_BAR_HEIGHT - FOOTER_HEIGHT,\r
- LocalScreen.BottomRow - STATUS_BAR_HEIGHT - 1,\r
- KEYHELP_TEXT | KEYHELP_BACKGROUND\r
- );\r
-\r
- if (gClassOfVfr != FORMSET_CLASS_FRONT_PAGE) {\r
- ClearLines (\r
- LocalScreen.LeftColumn,\r
- LocalScreen.RightColumn,\r
- LocalScreen.TopRow,\r
- LocalScreen.TopRow + NONE_FRONT_PAGE_HEADER_HEIGHT - 1,\r
- TITLE_TEXT | TITLE_BACKGROUND\r
- );\r
- //\r
- // Print Top border line\r
- // +------------------------------------------------------------------------------+\r
- // ? ?\r
- // +------------------------------------------------------------------------------+\r
- //\r
- Character = BOXDRAW_DOWN_RIGHT;\r
-\r
- PrintChar (Character);\r
- PrintString (Buffer);\r
-\r
- Character = BOXDRAW_DOWN_LEFT;\r
- PrintChar (Character);\r
-\r
- Character = BOXDRAW_VERTICAL;\r
- for (Row = LocalScreen.TopRow + 1; Row <= LocalScreen.TopRow + NONE_FRONT_PAGE_HEADER_HEIGHT - 2; Row++) {\r
- PrintCharAt (LocalScreen.LeftColumn, Row, Character);\r
- PrintCharAt (LocalScreen.RightColumn - 1, Row, Character);\r
+ CopyMem (&DisplayStatement->CurrentValue, &Statement->HiiValue, sizeof (EFI_HII_VALUE));\r
+\r
+ //\r
+ // Some special op code need an extra buffer to save the data.\r
+ // Such as string, password, orderedlist...\r
+ //\r
+ if (Statement->BufferValue != NULL) {\r
+ //\r
+ // Ordered list opcode may not initilized, get default value here.\r
+ //\r
+ if (Statement->OpCode->OpCode == EFI_IFR_ORDERED_LIST_OP && GetArrayData (Statement->BufferValue, Statement->ValueType, 0) == 0) {\r
+ GetQuestionDefault (gCurrentSelection->FormSet, gCurrentSelection->Form, Statement, 0);\r
}\r
\r
- Character = BOXDRAW_UP_RIGHT;\r
- PrintCharAt (LocalScreen.LeftColumn, LocalScreen.TopRow + NONE_FRONT_PAGE_HEADER_HEIGHT - 1, Character);\r
- PrintString (Buffer);\r
+ DisplayStatement->CurrentValue.Buffer = AllocateCopyPool(Statement->StorageWidth,Statement->BufferValue);\r
+ DisplayStatement->CurrentValue.BufferLen = Statement->StorageWidth;\r
+ }\r
\r
- Character = BOXDRAW_UP_LEFT;\r
- PrintChar (Character);\r
+ DisplayStatement->SettingChangedFlag = Statement->ValueChanged;\r
\r
- if (gClassOfVfr == FORMSET_CLASS_PLATFORM_SETUP) {\r
- //\r
- // Print Bottom border line\r
- // +------------------------------------------------------------------------------+\r
- // ? ?\r
- // +------------------------------------------------------------------------------+\r
- //\r
- Character = BOXDRAW_DOWN_RIGHT;\r
- PrintCharAt (LocalScreen.LeftColumn, LocalScreen.BottomRow - STATUS_BAR_HEIGHT - FOOTER_HEIGHT, Character);\r
-\r
- PrintString (Buffer);\r
-\r
- Character = BOXDRAW_DOWN_LEFT;\r
- PrintChar (Character);\r
- Character = BOXDRAW_VERTICAL;\r
- for (Row = LocalScreen.BottomRow - STATUS_BAR_HEIGHT - FOOTER_HEIGHT + 1;\r
- Row <= LocalScreen.BottomRow - STATUS_BAR_HEIGHT - 2;\r
- Row++\r
- ) {\r
- PrintCharAt (LocalScreen.LeftColumn, Row, Character);\r
- PrintCharAt (LocalScreen.RightColumn - 1, Row, Character);\r
- }\r
+ //\r
+ // Get the highlight statement for current form.\r
+ //\r
+ if (((gCurrentSelection->QuestionId != 0) && (Statement->QuestionId == gCurrentSelection->QuestionId)) ||\r
+ ((mCurFakeQestId != 0) && (Statement->FakeQuestionId == mCurFakeQestId))) {\r
+ gDisplayFormData.HighLightedStatement = DisplayStatement;\r
+ }\r
\r
- Character = BOXDRAW_UP_RIGHT;\r
- PrintCharAt (LocalScreen.LeftColumn, LocalScreen.BottomRow - STATUS_BAR_HEIGHT - 1, Character);\r
+ //\r
+ // Create the refresh event process function.\r
+ //\r
+ if (!CompareGuid (&Statement->RefreshGuid, &gZeroGuid)) {\r
+ CreateRefreshEvent (Statement);\r
+ }\r
\r
- PrintString (Buffer);\r
+ //\r
+ // For RTC type of date/time, set default refresh interval to be 1 second.\r
+ //\r
+ if ((Statement->Operand == EFI_IFR_DATE_OP || Statement->Operand == EFI_IFR_TIME_OP) && Statement->Storage == NULL) {\r
+ Statement->RefreshInterval = 1;\r
+ }\r
\r
- Character = BOXDRAW_UP_LEFT;\r
- PrintChar (Character);\r
- }\r
+ //\r
+ // Create the refresh guid hook event.\r
+ // If the statement in this form has refresh event or refresh interval, browser will create this event for display engine.\r
+ //\r
+ if ((!CompareGuid (&Statement->RefreshGuid, &gZeroGuid)) || (Statement->RefreshInterval != 0)) {\r
+ gDisplayFormData.FormRefreshEvent = mValueChangedEvent;\r
}\r
\r
- FreePool (Buffer);\r
+ //\r
+ // Save the password check function for later use.\r
+ //\r
+ if (Statement->Operand == EFI_IFR_PASSWORD_OP) {\r
+ DisplayStatement->PasswordCheck = PasswordCheck;\r
+ }\r
\r
-}\r
+ //\r
+ // Save the validate check question for later use.\r
+ //\r
+ if (!IsListEmpty (&Statement->InconsistentListHead)) {\r
+ DisplayStatement->ValidateQuestion = QuestionCheck;\r
+ }\r
\r
+ //\r
+ // If this statement is nest in the subtitle, insert to the host statement.\r
+ // else insert to the form it belongs to.\r
+ //\r
+ if (Statement->InSubtitle) {\r
+ InsertTailList(&HostDisplayStatement->NestStatementList, &DisplayStatement->DisplayLink);\r
+ } else {\r
+ InsertTailList(&gDisplayFormData.StatementListHead, &DisplayStatement->DisplayLink);\r
+ }\r
+}\r
\r
/**\r
- Evaluate all expressions in a Form.\r
-\r
- @param FormSet FormSet this Form belongs to.\r
- @param Form The Form.\r
+ Process for the refresh interval statement.\r
\r
- @retval EFI_SUCCESS The expression evaluated successfuly\r
+ @param Event The Event need to be process\r
+ @param Context The context of the event.\r
\r
**/\r
-EFI_STATUS\r
-EvaluateFormExpressions (\r
- IN FORM_BROWSER_FORMSET *FormSet,\r
- IN FORM_BROWSER_FORM *Form\r
+VOID\r
+EFIAPI\r
+RefreshIntervalProcess (\r
+ IN EFI_EVENT Event,\r
+ IN VOID *Context\r
)\r
{\r
- EFI_STATUS Status;\r
- LIST_ENTRY *Link;\r
- FORM_EXPRESSION *Expression;\r
+ FORM_BROWSER_STATEMENT *Statement;\r
+ LIST_ENTRY *Link;\r
\r
- Link = GetFirstNode (&Form->ExpressionListHead);\r
- while (!IsNull (&Form->ExpressionListHead, Link)) {\r
- Expression = FORM_EXPRESSION_FROM_LINK (Link);\r
- Link = GetNextNode (&Form->ExpressionListHead, Link);\r
+ Link = GetFirstNode (&gCurrentSelection->Form->StatementListHead);\r
+ while (!IsNull (&gCurrentSelection->Form->StatementListHead, Link)) {\r
+ Statement = FORM_BROWSER_STATEMENT_FROM_LINK (Link);\r
+ Link = GetNextNode (&gCurrentSelection->Form->StatementListHead, Link);\r
\r
- if (Expression->Type == EFI_HII_EXPRESSION_INCONSISTENT_IF ||\r
- Expression->Type == EFI_HII_EXPRESSION_NO_SUBMIT_IF) {\r
- //\r
- // Postpone Form validation to Question editing or Form submiting\r
- //\r
+ if (Statement->RefreshInterval == 0) {\r
continue;\r
}\r
\r
- Status = EvaluateExpression (FormSet, Form, Expression);\r
- if (EFI_ERROR (Status)) {\r
- return Status;\r
- }\r
+ UpdateStatement(Statement);\r
}\r
\r
- return EFI_SUCCESS;\r
+ gBS->SignalEvent (mValueChangedEvent);\r
}\r
\r
-/*\r
-+------------------------------------------------------------------------------+\r
-? Setup Page ?\r
-+------------------------------------------------------------------------------+\r
-\r
+/**\r
\r
+ Make a copy of the global hotkey info.\r
\r
+**/\r
+VOID\r
+UpdateHotkeyList (\r
+ VOID\r
+ )\r
+{\r
+ BROWSER_HOT_KEY *HotKey;\r
+ BROWSER_HOT_KEY *CopyKey;\r
+ LIST_ENTRY *Link;\r
\r
+ Link = GetFirstNode (&gBrowserHotKeyList);\r
+ while (!IsNull (&gBrowserHotKeyList, Link)) {\r
+ HotKey = BROWSER_HOT_KEY_FROM_LINK (Link);\r
\r
+ CopyKey = AllocateCopyPool(sizeof (BROWSER_HOT_KEY), HotKey);\r
+ CopyKey->KeyData = AllocateCopyPool(sizeof (EFI_INPUT_KEY), HotKey->KeyData);\r
+ CopyKey->HelpString = AllocateCopyPool(StrSize (HotKey->HelpString), HotKey->HelpString);\r
\r
+ InsertTailList(&gDisplayFormData.HotKeyListHead, &CopyKey->Link);\r
\r
+ Link = GetNextNode (&gBrowserHotKeyList, Link);\r
+ }\r
+}\r
\r
+/**\r
\r
+ Enum all statement in current form, find all the statement can be display and\r
+ add to the display form.\r
\r
+**/\r
+VOID\r
+AddStatementToDisplayForm (\r
+ VOID\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ LIST_ENTRY *Link;\r
+ FORM_BROWSER_STATEMENT *Statement;\r
+ FORM_DISPLAY_ENGINE_STATEMENT *DisplayStatement;\r
+ FORM_DISPLAY_ENGINE_STATEMENT *HostDisplayStatement;\r
+ UINT8 MinRefreshInterval;\r
+ EFI_EVENT RefreshIntervalEvent;\r
+ FORM_BROWSER_REFRESH_EVENT_NODE *EventNode;\r
+ BOOLEAN FormEditable;\r
+\r
+ HostDisplayStatement = NULL;\r
+ MinRefreshInterval = 0;\r
+ FormEditable = FALSE;\r
\r
+ //\r
+ // Process the statement outside the form, these statements are not recognized\r
+ // by browser core.\r
+ //\r
+ Link = GetFirstNode (&gCurrentSelection->FormSet->StatementListOSF);\r
+ while (!IsNull (&gCurrentSelection->FormSet->StatementListOSF, Link)) {\r
+ Statement = FORM_BROWSER_STATEMENT_FROM_LINK (Link);\r
+ Link = GetNextNode (&gCurrentSelection->FormSet->StatementListOSF, Link);\r
\r
+ DisplayStatement = AllocateZeroPool (sizeof (FORM_DISPLAY_ENGINE_STATEMENT));\r
+ ASSERT (DisplayStatement != NULL);\r
+ DisplayStatement->Signature = FORM_DISPLAY_ENGINE_STATEMENT_SIGNATURE;\r
+ DisplayStatement->Version = FORM_DISPLAY_ENGINE_STATEMENT_VERSION_1;\r
+ DisplayStatement->OpCode = Statement->OpCode;\r
\r
+ InitializeListHead (&DisplayStatement->NestStatementList);\r
+ InitializeListHead (&DisplayStatement->OptionListHead);\r
\r
+ InsertTailList(&gDisplayFormData.StatementListOSF, &DisplayStatement->DisplayLink);\r
+ }\r
\r
+ //\r
+ // Process the statement in this form.\r
+ //\r
+ Link = GetFirstNode (&gCurrentSelection->Form->StatementListHead);\r
+ while (!IsNull (&gCurrentSelection->Form->StatementListHead, Link)) {\r
+ Statement = FORM_BROWSER_STATEMENT_FROM_LINK (Link);\r
+ Link = GetNextNode (&gCurrentSelection->Form->StatementListHead, Link);\r
\r
+ //\r
+ // This statement can't be show, skip it.\r
+ //\r
+ if (EvaluateExpressionList(Statement->Expression, FALSE, NULL, NULL) > ExpressGrayOut) {\r
+ continue;\r
+ }\r
\r
-+------------------------------------------------------------------------------+\r
-?F1=Scroll Help F9=Reset to Defaults F10=Save and Exit ?\r
-| ^"=Move Highlight <Spacebar> Toggles Checkbox Esc=Discard Changes |\r
-+------------------------------------------------------------------------------+\r
-*/\r
+ DisplayStatement = AllocateZeroPool (sizeof (FORM_DISPLAY_ENGINE_STATEMENT));\r
+ ASSERT (DisplayStatement != NULL);\r
\r
-/**\r
+ //\r
+ // Initialize this statement and add it to the display form.\r
+ //\r
+ InitializeDisplayStatement(DisplayStatement, Statement, HostDisplayStatement);\r
\r
+ //\r
+ // Save the Host statement info.\r
+ // Host statement may has nest statement follow it.\r
+ //\r
+ if (!Statement->InSubtitle) {\r
+ HostDisplayStatement = DisplayStatement;\r
+ }\r
\r
- Display form and wait for user to select one menu option, then return it.\r
+ if (Statement->Storage != NULL) {\r
+ FormEditable = TRUE;\r
+ }\r
+\r
+ //\r
+ // Get the minimal refresh interval value for later use.\r
+ //\r
+ if ((Statement->RefreshInterval != 0) && \r
+ (MinRefreshInterval == 0 || Statement->RefreshInterval < MinRefreshInterval)) {\r
+ MinRefreshInterval = Statement->RefreshInterval;\r
+ }\r
+ }\r
+\r
+ //\r
+ // Create the periodic timer for refresh interval statement.\r
+ //\r
+ if (MinRefreshInterval != 0) {\r
+ Status = gBS->CreateEvent (EVT_TIMER | EVT_NOTIFY_SIGNAL, TPL_CALLBACK, RefreshIntervalProcess, NULL, &RefreshIntervalEvent);\r
+ ASSERT_EFI_ERROR (Status);\r
+ Status = gBS->SetTimer (RefreshIntervalEvent, TimerPeriodic, MinRefreshInterval * ONE_SECOND);\r
+ ASSERT_EFI_ERROR (Status);\r
+\r
+ EventNode = AllocateZeroPool (sizeof (FORM_BROWSER_REFRESH_EVENT_NODE));\r
+ ASSERT (EventNode != NULL);\r
+ EventNode->RefreshEvent = RefreshIntervalEvent;\r
+ InsertTailList(&mRefreshEventList, &EventNode->Link);\r
+ }\r
+\r
+ //\r
+ // Update hotkey list field.\r
+ //\r
+ if (gBrowserSettingScope == SystemLevel || FormEditable) {\r
+ UpdateHotkeyList();\r
+ }\r
+}\r
+\r
+/**\r
+\r
+ Initialize the SettingChangedFlag variable in the display form.\r
+\r
+**/\r
+VOID\r
+UpdateDataChangedFlag (\r
+ VOID\r
+ )\r
+{\r
+ LIST_ENTRY *Link;\r
+ FORM_BROWSER_FORMSET *LocalFormSet;\r
+\r
+ gDisplayFormData.SettingChangedFlag = FALSE;\r
+\r
+ if (IsNvUpdateRequiredForForm (gCurrentSelection->Form)) {\r
+ gDisplayFormData.SettingChangedFlag = TRUE;\r
+ return;\r
+ }\r
+\r
+ //\r
+ // Base on the system level to check whether need to show the NV flag.\r
+ // \r
+ switch (gBrowserSettingScope) {\r
+ case SystemLevel:\r
+ //\r
+ // Check the maintain list to see whether there is any change.\r
+ //\r
+ Link = GetFirstNode (&gBrowserFormSetList);\r
+ while (!IsNull (&gBrowserFormSetList, Link)) {\r
+ LocalFormSet = FORM_BROWSER_FORMSET_FROM_LINK (Link);\r
+ if (IsNvUpdateRequiredForFormSet(LocalFormSet)) {\r
+ gDisplayFormData.SettingChangedFlag = TRUE;\r
+ return;\r
+ }\r
+ Link = GetNextNode (&gBrowserFormSetList, Link);\r
+ }\r
+ break;\r
+\r
+ case FormSetLevel:\r
+ if (IsNvUpdateRequiredForFormSet(gCurrentSelection->FormSet)) {\r
+ gDisplayFormData.SettingChangedFlag = TRUE;\r
+ return;\r
+ }\r
+ break;\r
+\r
+ default:\r
+ break;\r
+ }\r
+}\r
+\r
+/**\r
+\r
+ Initialize the Display form structure data.\r
+\r
+**/\r
+VOID\r
+InitializeDisplayFormData (\r
+ VOID\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+\r
+ gDisplayFormData.Signature = FORM_DISPLAY_ENGINE_FORM_SIGNATURE;\r
+ gDisplayFormData.Version = FORM_DISPLAY_ENGINE_VERSION_1;\r
+ gDisplayFormData.ImageId = 0;\r
+ gDisplayFormData.AnimationId = 0;\r
+\r
+ InitializeListHead (&gDisplayFormData.StatementListHead);\r
+ InitializeListHead (&gDisplayFormData.StatementListOSF);\r
+ InitializeListHead (&gDisplayFormData.HotKeyListHead);\r
+\r
+ Status = gBS->CreateEvent (\r
+ EVT_NOTIFY_WAIT, \r
+ TPL_CALLBACK,\r
+ SetupBrowserEmptyFunction,\r
+ NULL,\r
+ &mValueChangedEvent\r
+ );\r
+ ASSERT_EFI_ERROR (Status); \r
+}\r
+\r
+/**\r
+\r
+ Free the kotkey info saved in form data.\r
+\r
+**/\r
+VOID\r
+FreeHotkeyList (\r
+ VOID\r
+ )\r
+{\r
+ BROWSER_HOT_KEY *HotKey;\r
+ LIST_ENTRY *Link;\r
+\r
+ while (!IsListEmpty (&gDisplayFormData.HotKeyListHead)) {\r
+ Link = GetFirstNode (&gDisplayFormData.HotKeyListHead);\r
+ HotKey = BROWSER_HOT_KEY_FROM_LINK (Link);\r
+\r
+ RemoveEntryList (&HotKey->Link);\r
+\r
+ FreePool (HotKey->KeyData);\r
+ FreePool (HotKey->HelpString);\r
+ FreePool (HotKey);\r
+ }\r
+}\r
+\r
+/**\r
+\r
+ Update the Display form structure data.\r
+\r
+**/\r
+VOID\r
+UpdateDisplayFormData (\r
+ VOID\r
+ )\r
+{\r
+ gDisplayFormData.FormTitle = gCurrentSelection->Form->FormTitle;\r
+ gDisplayFormData.FormId = gCurrentSelection->FormId;\r
+ gDisplayFormData.HiiHandle = gCurrentSelection->Handle;\r
+ CopyGuid (&gDisplayFormData.FormSetGuid, &gCurrentSelection->FormSetGuid);\r
+\r
+ gDisplayFormData.Attribute = 0;\r
+ gDisplayFormData.Attribute |= gCurrentSelection->Form->ModalForm ? HII_DISPLAY_MODAL : 0;\r
+ gDisplayFormData.Attribute |= gCurrentSelection->Form->Locked ? HII_DISPLAY_LOCK : 0;\r
+\r
+ gDisplayFormData.FormRefreshEvent = NULL;\r
+ gDisplayFormData.HighLightedStatement = NULL;\r
+\r
+ gDisplayFormData.BrowserStatus = gBrowserStatus;\r
+ gDisplayFormData.ErrorString = gErrorInfo;\r
+\r
+ gBrowserStatus = BROWSER_SUCCESS;\r
+ gErrorInfo = NULL;\r
+\r
+ UpdateDataChangedFlag ();\r
+\r
+ AddStatementToDisplayForm ();\r
+}\r
+\r
+/**\r
+\r
+ Free the Display Statement structure data.\r
+\r
+ @param StatementList Point to the statement list which need to be free.\r
+\r
+**/\r
+VOID\r
+FreeStatementData (\r
+ LIST_ENTRY *StatementList\r
+ )\r
+{\r
+ LIST_ENTRY *Link;\r
+ LIST_ENTRY *OptionLink;\r
+ FORM_DISPLAY_ENGINE_STATEMENT *Statement;\r
+ DISPLAY_QUESTION_OPTION *Option;\r
+\r
+ //\r
+ // Free Statements/Questions\r
+ //\r
+ while (!IsListEmpty (StatementList)) {\r
+ Link = GetFirstNode (StatementList);\r
+ Statement = FORM_DISPLAY_ENGINE_STATEMENT_FROM_LINK (Link);\r
+\r
+ //\r
+ // Free Options List\r
+ //\r
+ while (!IsListEmpty (&Statement->OptionListHead)) {\r
+ OptionLink = GetFirstNode (&Statement->OptionListHead);\r
+ Option = DISPLAY_QUESTION_OPTION_FROM_LINK (OptionLink);\r
+ RemoveEntryList (&Option->Link);\r
+ FreePool (Option);\r
+ }\r
+\r
+ //\r
+ // Free nest statement List\r
+ //\r
+ if (!IsListEmpty (&Statement->NestStatementList)) {\r
+ FreeStatementData(&Statement->NestStatementList);\r
+ }\r
+\r
+ RemoveEntryList (&Statement->DisplayLink);\r
+ FreePool (Statement);\r
+ }\r
+}\r
+\r
+/**\r
+\r
+ Free the Display form structure data.\r
+\r
+**/\r
+VOID\r
+FreeDisplayFormData (\r
+ VOID\r
+ )\r
+{\r
+ FreeStatementData (&gDisplayFormData.StatementListHead);\r
+ FreeStatementData (&gDisplayFormData.StatementListOSF);\r
+\r
+ FreeRefreshEvent();\r
+\r
+ FreeHotkeyList();\r
+}\r
+\r
+/**\r
+\r
+ Get FORM_BROWSER_STATEMENT from FORM_DISPLAY_ENGINE_STATEMENT based on the OpCode info.\r
+\r
+ @param DisplayStatement The input FORM_DISPLAY_ENGINE_STATEMENT.\r
+\r
+ @retval FORM_BROWSER_STATEMENT The return FORM_BROWSER_STATEMENT info.\r
+\r
+**/\r
+FORM_BROWSER_STATEMENT *\r
+GetBrowserStatement (\r
+ IN FORM_DISPLAY_ENGINE_STATEMENT *DisplayStatement\r
+ )\r
+{\r
+ FORM_BROWSER_STATEMENT *Statement;\r
+ LIST_ENTRY *Link;\r
+\r
+ Link = GetFirstNode (&gCurrentSelection->Form->StatementListHead);\r
+ while (!IsNull (&gCurrentSelection->Form->StatementListHead, Link)) {\r
+ Statement = FORM_BROWSER_STATEMENT_FROM_LINK (Link);\r
+\r
+ if (Statement->OpCode == DisplayStatement->OpCode) {\r
+ return Statement;\r
+ }\r
+\r
+ Link = GetNextNode (&gCurrentSelection->Form->StatementListHead, Link);\r
+ }\r
+\r
+ return NULL;\r
+}\r
+\r
+/**\r
+\r
+ Process the action request in user input.\r
+\r
+ @param Action The user input action request info.\r
+ @param DefaultId The user input default Id info.\r
+\r
+ @retval EFI_SUCESSS This function always return successfully for now.\r
+\r
+**/\r
+EFI_STATUS \r
+ProcessAction (\r
+ IN UINT32 Action,\r
+ IN UINT16 DefaultId\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+\r
+ //\r
+ // This is caused by use press ESC, and it should not combine with other action type.\r
+ //\r
+ if ((Action & BROWSER_ACTION_FORM_EXIT) == BROWSER_ACTION_FORM_EXIT) {\r
+ FindNextMenu (gCurrentSelection, FormLevel);\r
+ return EFI_SUCCESS;\r
+ }\r
+\r
+ //\r
+ // Below is normal hotkey trigged action, these action maybe combine with each other.\r
+ //\r
+ if ((Action & BROWSER_ACTION_DISCARD) == BROWSER_ACTION_DISCARD) {\r
+ DiscardForm (gCurrentSelection->FormSet, gCurrentSelection->Form, gBrowserSettingScope);\r
+ }\r
+\r
+ if ((Action & BROWSER_ACTION_DEFAULT) == BROWSER_ACTION_DEFAULT) {\r
+ ExtractDefault (gCurrentSelection->FormSet, gCurrentSelection->Form, DefaultId, gBrowserSettingScope, GetDefaultForAll, NULL, FALSE);\r
+ }\r
+\r
+ if ((Action & BROWSER_ACTION_SUBMIT) == BROWSER_ACTION_SUBMIT) {\r
+ Status = SubmitForm (gCurrentSelection->FormSet, gCurrentSelection->Form, gBrowserSettingScope);\r
+ if (EFI_ERROR (Status)) {\r
+ gBrowserStatus = BROWSER_SUBMIT_FAIL;\r
+ }\r
+ }\r
+\r
+ if ((Action & BROWSER_ACTION_RESET) == BROWSER_ACTION_RESET) {\r
+ gResetRequired = TRUE;\r
+ }\r
+\r
+ if ((Action & BROWSER_ACTION_EXIT) == BROWSER_ACTION_EXIT) {\r
+ //\r
+ // Form Exit without saving, Similar to ESC Key.\r
+ // FormSet Exit without saving, Exit SendForm.\r
+ // System Exit without saving, CallExitHandler and Exit SendForm.\r
+ //\r
+ DiscardForm (gCurrentSelection->FormSet, gCurrentSelection->Form, gBrowserSettingScope);\r
+ if (gBrowserSettingScope == FormLevel || gBrowserSettingScope == FormSetLevel) {\r
+ FindNextMenu (gCurrentSelection, gBrowserSettingScope);\r
+ } else if (gBrowserSettingScope == SystemLevel) {\r
+ if (ExitHandlerFunction != NULL) {\r
+ ExitHandlerFunction ();\r
+ }\r
+ gCurrentSelection->Action = UI_ACTION_EXIT;\r
+ }\r
+ }\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+\r
+/**\r
+ Find HII Handle in the HII database associated with given Device Path.\r
+\r
+ If DevicePath is NULL, then ASSERT.\r
+\r
+ @param DevicePath Device Path associated with the HII package list\r
+ handle.\r
+\r
+ @retval Handle HII package list Handle associated with the Device\r
+ Path.\r
+ @retval NULL Hii Package list handle is not found.\r
+\r
+**/\r
+EFI_HII_HANDLE\r
+EFIAPI\r
+DevicePathToHiiHandle (\r
+ IN EFI_DEVICE_PATH_PROTOCOL *DevicePath\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ EFI_DEVICE_PATH_PROTOCOL *TmpDevicePath;\r
+ UINTN BufferSize;\r
+ UINTN HandleCount;\r
+ UINTN Index;\r
+ EFI_HANDLE Handle;\r
+ EFI_HANDLE DriverHandle;\r
+ EFI_HII_HANDLE *HiiHandles;\r
+ EFI_HII_HANDLE HiiHandle;\r
+\r
+ ASSERT (DevicePath != NULL);\r
+\r
+ TmpDevicePath = DevicePath;\r
+ //\r
+ // Locate Device Path Protocol handle buffer\r
+ //\r
+ Status = gBS->LocateDevicePath (\r
+ &gEfiDevicePathProtocolGuid,\r
+ &TmpDevicePath,\r
+ &DriverHandle\r
+ );\r
+ if (EFI_ERROR (Status) || !IsDevicePathEnd (TmpDevicePath)) {\r
+ return NULL;\r
+ }\r
+\r
+ //\r
+ // Retrieve all HII Handles from HII database\r
+ //\r
+ BufferSize = 0x1000;\r
+ HiiHandles = AllocatePool (BufferSize);\r
+ ASSERT (HiiHandles != NULL);\r
+ Status = mHiiDatabase->ListPackageLists (\r
+ mHiiDatabase,\r
+ EFI_HII_PACKAGE_TYPE_ALL,\r
+ NULL,\r
+ &BufferSize,\r
+ HiiHandles\r
+ );\r
+ if (Status == EFI_BUFFER_TOO_SMALL) {\r
+ FreePool (HiiHandles);\r
+ HiiHandles = AllocatePool (BufferSize);\r
+ ASSERT (HiiHandles != NULL);\r
+\r
+ Status = mHiiDatabase->ListPackageLists (\r
+ mHiiDatabase,\r
+ EFI_HII_PACKAGE_TYPE_ALL,\r
+ NULL,\r
+ &BufferSize,\r
+ HiiHandles\r
+ );\r
+ }\r
+\r
+ if (EFI_ERROR (Status)) {\r
+ FreePool (HiiHandles);\r
+ return NULL;\r
+ }\r
+\r
+ //\r
+ // Search Hii Handle by Driver Handle\r
+ //\r
+ HiiHandle = NULL;\r
+ HandleCount = BufferSize / sizeof (EFI_HII_HANDLE);\r
+ for (Index = 0; Index < HandleCount; Index++) {\r
+ Status = mHiiDatabase->GetPackageListHandle (\r
+ mHiiDatabase,\r
+ HiiHandles[Index],\r
+ &Handle\r
+ );\r
+ if (!EFI_ERROR (Status) && (Handle == DriverHandle)) {\r
+ HiiHandle = HiiHandles[Index];\r
+ break;\r
+ }\r
+ }\r
+\r
+ FreePool (HiiHandles);\r
+ return HiiHandle;\r
+}\r
+\r
+/**\r
+ Find HII Handle in the HII database associated with given form set guid.\r
+\r
+ If FormSetGuid is NULL, then ASSERT.\r
+\r
+ @param ComparingGuid FormSet Guid associated with the HII package list\r
+ handle.\r
+\r
+ @retval Handle HII package list Handle associated with the Device\r
+ Path.\r
+ @retval NULL Hii Package list handle is not found.\r
+\r
+**/\r
+EFI_HII_HANDLE\r
+FormSetGuidToHiiHandle (\r
+ EFI_GUID *ComparingGuid\r
+ )\r
+{\r
+ EFI_HII_HANDLE *HiiHandles;\r
+ UINTN Index;\r
+ EFI_HII_PACKAGE_LIST_HEADER *HiiPackageList;\r
+ UINTN BufferSize;\r
+ UINT32 Offset;\r
+ UINT32 Offset2;\r
+ UINT32 PackageListLength;\r
+ EFI_HII_PACKAGE_HEADER PackageHeader;\r
+ UINT8 *Package;\r
+ UINT8 *OpCodeData;\r
+ EFI_STATUS Status;\r
+ EFI_HII_HANDLE HiiHandle;\r
+\r
+ ASSERT (ComparingGuid != NULL);\r
+\r
+ HiiHandle = NULL;\r
+ //\r
+ // Get all the Hii handles\r
+ //\r
+ HiiHandles = HiiGetHiiHandles (NULL);\r
+ ASSERT (HiiHandles != NULL);\r
+\r
+ //\r
+ // Search for formset of each class type\r
+ //\r
+ for (Index = 0; HiiHandles[Index] != NULL; Index++) {\r
+ BufferSize = 0;\r
+ HiiPackageList = NULL;\r
+ Status = mHiiDatabase->ExportPackageLists (mHiiDatabase, HiiHandles[Index], &BufferSize, HiiPackageList);\r
+ if (Status == EFI_BUFFER_TOO_SMALL) {\r
+ HiiPackageList = AllocatePool (BufferSize);\r
+ ASSERT (HiiPackageList != NULL);\r
+\r
+ Status = mHiiDatabase->ExportPackageLists (mHiiDatabase, HiiHandles[Index], &BufferSize, HiiPackageList);\r
+ }\r
+ if (EFI_ERROR (Status) || HiiPackageList == NULL) {\r
+ return NULL;\r
+ }\r
+\r
+ //\r
+ // Get Form package from this HII package List\r
+ //\r
+ Offset = sizeof (EFI_HII_PACKAGE_LIST_HEADER);\r
+ Offset2 = 0;\r
+ CopyMem (&PackageListLength, &HiiPackageList->PackageLength, sizeof (UINT32)); \r
+\r
+ while (Offset < PackageListLength) {\r
+ Package = ((UINT8 *) HiiPackageList) + Offset;\r
+ CopyMem (&PackageHeader, Package, sizeof (EFI_HII_PACKAGE_HEADER));\r
+\r
+ if (PackageHeader.Type == EFI_HII_PACKAGE_FORMS) {\r
+ //\r
+ // Search FormSet in this Form Package\r
+ //\r
+ Offset2 = sizeof (EFI_HII_PACKAGE_HEADER);\r
+ while (Offset2 < PackageHeader.Length) {\r
+ OpCodeData = Package + Offset2;\r
+\r
+ if (((EFI_IFR_OP_HEADER *) OpCodeData)->OpCode == EFI_IFR_FORM_SET_OP) {\r
+ //\r
+ // Try to compare against formset GUID\r
+ //\r
+ if (CompareGuid (ComparingGuid, (EFI_GUID *)(OpCodeData + sizeof (EFI_IFR_OP_HEADER)))) {\r
+ HiiHandle = HiiHandles[Index];\r
+ break;\r
+ }\r
+ }\r
+\r
+ Offset2 += ((EFI_IFR_OP_HEADER *) OpCodeData)->Length;\r
+ }\r
+ }\r
+ if (HiiHandle != NULL) {\r
+ break;\r
+ }\r
+ Offset += PackageHeader.Length;\r
+ }\r
+ \r
+ FreePool (HiiPackageList);\r
+ if (HiiHandle != NULL) {\r
+ break;\r
+ }\r
+ }\r
+\r
+ FreePool (HiiHandles);\r
+\r
+ return HiiHandle;\r
+}\r
+\r
+/**\r
+ check how to process the changed data in current form or form set.\r
\r
@param Selection On input, Selection tell setup browser the information\r
about the Selection, form and formset to be displayed.\r
On output, Selection return the screen item that is selected\r
by user.\r
+\r
+ @param Scope Data save or discard scope, form or formset.\r
+\r
+ @retval TRUE Success process the changed data, will return to the parent form.\r
+ @retval FALSE Reject to process the changed data, will stay at current form.\r
+**/\r
+BOOLEAN\r
+ProcessChangedData (\r
+ IN OUT UI_MENU_SELECTION *Selection,\r
+ IN BROWSER_SETTING_SCOPE Scope\r
+ )\r
+{\r
+ BOOLEAN RetValue;\r
+\r
+ RetValue = TRUE;\r
+ switch (mFormDisplay->ConfirmDataChange()) {\r
+ case BROWSER_ACTION_DISCARD:\r
+ DiscardForm (Selection->FormSet, Selection->Form, Scope);\r
+ break;\r
+ \r
+ case BROWSER_ACTION_SUBMIT:\r
+ SubmitForm (Selection->FormSet, Selection->Form, Scope);\r
+ break;\r
+\r
+ case BROWSER_ACTION_NONE:\r
+ RetValue = FALSE;\r
+ break;\r
+\r
+ default:\r
+ //\r
+ // if Invalid value return, process same as BROWSER_ACTION_NONE.\r
+ //\r
+ RetValue = FALSE;\r
+ break;\r
+ }\r
+\r
+ return RetValue;\r
+}\r
+\r
+/**\r
+ Find parent formset menu(the first menu which has different formset) for current menu.\r
+ If not find, just return to the first menu.\r
+\r
+ @param Selection The selection info.\r
+\r
+**/\r
+VOID\r
+FindParentFormSet (\r
+ IN OUT UI_MENU_SELECTION *Selection\r
+ )\r
+{\r
+ FORM_ENTRY_INFO *CurrentMenu;\r
+ FORM_ENTRY_INFO *ParentMenu;\r
+\r
+ CurrentMenu = Selection->CurrentMenu;\r
+ ParentMenu = UiFindParentMenu(CurrentMenu);\r
+\r
+ //\r
+ // Find a menu which has different formset guid with current.\r
+ //\r
+ while (ParentMenu != NULL && CompareGuid (&CurrentMenu->FormSetGuid, &ParentMenu->FormSetGuid)) {\r
+ CurrentMenu = ParentMenu;\r
+ ParentMenu = UiFindParentMenu(CurrentMenu);\r
+ }\r
+\r
+ if (ParentMenu != NULL) {\r
+ CopyMem (&Selection->FormSetGuid, &ParentMenu->FormSetGuid, sizeof (EFI_GUID));\r
+ Selection->Handle = ParentMenu->HiiHandle;\r
+ Selection->FormId = ParentMenu->FormId;\r
+ Selection->QuestionId = ParentMenu->QuestionId;\r
+ } else {\r
+ Selection->FormId = CurrentMenu->FormId;\r
+ Selection->QuestionId = CurrentMenu->QuestionId;\r
+ }\r
+\r
+ Selection->Statement = NULL;\r
+}\r
+\r
+/**\r
+ Process the goto op code, update the info in the selection structure.\r
+\r
+ @param Statement The statement belong to goto op code.\r
+ @param Selection The selection info.\r
+\r
+ @retval EFI_SUCCESS The menu process successfully.\r
+ @return Other value if the process failed.\r
+**/\r
+EFI_STATUS\r
+ProcessGotoOpCode (\r
+ IN OUT FORM_BROWSER_STATEMENT *Statement,\r
+ IN OUT UI_MENU_SELECTION *Selection\r
+ )\r
+{\r
+ CHAR16 *StringPtr;\r
+ EFI_DEVICE_PATH_PROTOCOL *DevicePath;\r
+ FORM_BROWSER_FORM *RefForm;\r
+ EFI_STATUS Status;\r
+ EFI_HII_HANDLE HiiHandle;\r
+ \r
+ Status = EFI_SUCCESS;\r
+ StringPtr = NULL;\r
+ HiiHandle = NULL;\r
+\r
+ //\r
+ // Prepare the device path check, get the device path info first.\r
+ //\r
+ if (Statement->HiiValue.Value.ref.DevicePath != 0) {\r
+ StringPtr = GetToken (Statement->HiiValue.Value.ref.DevicePath, Selection->FormSet->HiiHandle);\r
+ }\r
+\r
+ //\r
+ // Check whether the device path string is a valid string.\r
+ //\r
+ if (Statement->HiiValue.Value.ref.DevicePath != 0 && StringPtr != NULL) {\r
+ if (Selection->Form->ModalForm) {\r
+ return Status;\r
+ }\r
+\r
+ //\r
+ // Goto another Hii Package list\r
+ //\r
+ if (mPathFromText != NULL) {\r
+ DevicePath = mPathFromText->ConvertTextToDevicePath(StringPtr);\r
+ if (DevicePath != NULL) {\r
+ HiiHandle = DevicePathToHiiHandle (DevicePath);\r
+ FreePool (DevicePath);\r
+ }\r
+ FreePool (StringPtr);\r
+ } else {\r
+ //\r
+ // Not found the EFI_DEVICE_PATH_FROM_TEXT_PROTOCOL protocol.\r
+ //\r
+ gBrowserStatus = BROWSER_PROTOCOL_NOT_FOUND;\r
+ FreePool (StringPtr);\r
+ return Status;\r
+ }\r
+\r
+ if (HiiHandle != Selection->Handle) {\r
+ //\r
+ // Goto another Formset, check for uncommitted data\r
+ //\r
+ if ((gBrowserSettingScope == FormLevel || gBrowserSettingScope == FormSetLevel) &&\r
+ IsNvUpdateRequiredForFormSet(Selection->FormSet)) {\r
+ if (!ProcessChangedData(Selection, FormSetLevel)) {\r
+ return EFI_SUCCESS;\r
+ }\r
+ }\r
+ }\r
+\r
+ Selection->Action = UI_ACTION_REFRESH_FORMSET;\r
+ Selection->Handle = HiiHandle;\r
+ if (Selection->Handle == NULL) {\r
+ //\r
+ // If target Hii Handle not found, exit current formset.\r
+ //\r
+ FindParentFormSet(Selection);\r
+ return EFI_SUCCESS;\r
+ }\r
+\r
+ CopyMem (&Selection->FormSetGuid,&Statement->HiiValue.Value.ref.FormSetGuid, sizeof (EFI_GUID));\r
+ Selection->FormId = Statement->HiiValue.Value.ref.FormId;\r
+ Selection->QuestionId = Statement->HiiValue.Value.ref.QuestionId;\r
+ } else if (!CompareGuid (&Statement->HiiValue.Value.ref.FormSetGuid, &gZeroGuid)) {\r
+ if (Selection->Form->ModalForm) {\r
+ return Status;\r
+ }\r
+ if (!CompareGuid (&Statement->HiiValue.Value.ref.FormSetGuid, &Selection->FormSetGuid)) {\r
+ //\r
+ // Goto another Formset, check for uncommitted data\r
+ //\r
+ if ((gBrowserSettingScope == FormLevel || gBrowserSettingScope == FormSetLevel) &&\r
+ IsNvUpdateRequiredForFormSet(Selection->FormSet)) {\r
+ if (!ProcessChangedData(Selection, FormSetLevel)) {\r
+ return EFI_SUCCESS;\r
+ }\r
+ }\r
+ }\r
+\r
+ Selection->Action = UI_ACTION_REFRESH_FORMSET;\r
+ Selection->Handle = FormSetGuidToHiiHandle(&Statement->HiiValue.Value.ref.FormSetGuid);\r
+ if (Selection->Handle == NULL) {\r
+ //\r
+ // If target Hii Handle not found, exit current formset.\r
+ //\r
+ FindParentFormSet(Selection);\r
+ return EFI_SUCCESS;\r
+ }\r
+\r
+ CopyMem (&Selection->FormSetGuid, &Statement->HiiValue.Value.ref.FormSetGuid, sizeof (EFI_GUID));\r
+ Selection->FormId = Statement->HiiValue.Value.ref.FormId;\r
+ Selection->QuestionId = Statement->HiiValue.Value.ref.QuestionId;\r
+ } else if (Statement->HiiValue.Value.ref.FormId != 0) {\r
+ //\r
+ // Goto another Form, check for uncommitted data\r
+ //\r
+ if (Statement->HiiValue.Value.ref.FormId != Selection->FormId) {\r
+ if ((gBrowserSettingScope == FormLevel && IsNvUpdateRequiredForForm(Selection->Form))) {\r
+ if (!ProcessChangedData (Selection, FormLevel)) {\r
+ return EFI_SUCCESS;\r
+ }\r
+ }\r
+ }\r
+\r
+ RefForm = IdToForm (Selection->FormSet, Statement->HiiValue.Value.ref.FormId);\r
+ if ((RefForm != NULL) && (RefForm->SuppressExpression != NULL)) {\r
+ if (EvaluateExpressionList(RefForm->SuppressExpression, TRUE, Selection->FormSet, RefForm) != ExpressFalse) {\r
+ //\r
+ // Form is suppressed. \r
+ //\r
+ gBrowserStatus = BROWSER_FORM_SUPPRESS;\r
+ return EFI_SUCCESS;\r
+ }\r
+ }\r
+\r
+ Selection->FormId = Statement->HiiValue.Value.ref.FormId;\r
+ Selection->QuestionId = Statement->HiiValue.Value.ref.QuestionId;\r
+ } else if (Statement->HiiValue.Value.ref.QuestionId != 0) {\r
+ Selection->QuestionId = Statement->HiiValue.Value.ref.QuestionId;\r
+ }\r
+\r
+ return Status;\r
+}\r
+\r
+\r
+/**\r
+ Process Question Config.\r
+\r
+ @param Selection The UI menu selection.\r
+ @param Question The Question to be peocessed.\r
+\r
+ @retval EFI_SUCCESS Question Config process success.\r
+ @retval Other Question Config process fail.\r
+\r
+**/\r
+EFI_STATUS\r
+ProcessQuestionConfig (\r
+ IN UI_MENU_SELECTION *Selection,\r
+ IN FORM_BROWSER_STATEMENT *Question\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ CHAR16 *ConfigResp;\r
+ CHAR16 *Progress;\r
+ EFI_HII_CONFIG_ACCESS_PROTOCOL *ConfigAccess;\r
+\r
+ if (Question->QuestionConfig == 0) {\r
+ return EFI_SUCCESS;\r
+ }\r
+\r
+ //\r
+ // Get <ConfigResp>\r
+ //\r
+ ConfigResp = GetToken (Question->QuestionConfig, Selection->FormSet->HiiHandle);\r
+ if (ConfigResp == NULL) {\r
+ return EFI_NOT_FOUND;\r
+ }\r
+\r
+ //\r
+ // Send config to Configuration Driver\r
+ //\r
+ ConfigAccess = Selection->FormSet->ConfigAccess;\r
+ if (ConfigAccess == NULL) {\r
+ return EFI_UNSUPPORTED;\r
+ }\r
+ Status = ConfigAccess->RouteConfig (\r
+ ConfigAccess,\r
+ ConfigResp,\r
+ &Progress\r
+ );\r
+\r
+ return Status;\r
+}\r
+\r
+/**\r
+\r
+ Process the user input data.\r
+\r
+ @param UserInput The user input data.\r
+ @param ChangeHighlight Whether need to change the highlight statement. \r
+\r
@retval EFI_SUCESSS This function always return successfully for now.\r
\r
**/\r
EFI_STATUS\r
-DisplayForm (\r
- IN OUT UI_MENU_SELECTION *Selection\r
+ProcessUserInput (\r
+ IN USER_INPUT *UserInput,\r
+ IN BOOLEAN ChangeHighlight\r
)\r
{\r
- CHAR16 *StringPtr;\r
- UINT16 MenuItemCount;\r
- EFI_HII_HANDLE Handle;\r
- BOOLEAN Suppress;\r
- EFI_SCREEN_DESCRIPTOR LocalScreen;\r
- UINT16 Width;\r
- UINTN ArrayEntry;\r
- CHAR16 *OutputString;\r
- LIST_ENTRY *Link;\r
- FORM_BROWSER_STATEMENT *Statement;\r
- UINT16 NumberOfLines;\r
- EFI_STATUS Status;\r
- UI_MENU_OPTION *MenuOption;\r
+ EFI_STATUS Status;\r
+ FORM_BROWSER_STATEMENT *Statement;\r
+\r
+ Status = EFI_SUCCESS;\r
+\r
+ //\r
+ // When Exit from FormDisplay function, one of the below two cases must be true.\r
+ //\r
+ ASSERT (UserInput->Action != 0 || UserInput->SelectedStatement != NULL);\r
+\r
+ //\r
+ // Remove the last highligh question id, this id will update when show next form.\r
+ //\r
+ gCurrentSelection->QuestionId = 0;\r
+\r
+ //\r
+ // First process the Action field in USER_INPUT.\r
+ //\r
+ if (UserInput->Action != 0) {\r
+ Status = ProcessAction (UserInput->Action, UserInput->DefaultId);\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ //\r
+ // Clear the highlight info.\r
+ //\r
+ gCurrentSelection->Statement = NULL;\r
+\r
+ if (UserInput->SelectedStatement != NULL) {\r
+ Statement = GetBrowserStatement(UserInput->SelectedStatement);\r
+ ASSERT (Statement != NULL);\r
+ //\r
+ // Save the current highlight menu in the menu history data.\r
+ // which will be used when later browse back to this form.\r
+ //\r
+ gCurrentSelection->CurrentMenu->QuestionId = Statement->QuestionId;\r
+ //\r
+ // For statement like text, actio, it not has question id.\r
+ // So use FakeQuestionId to save the question.\r
+ //\r
+ if (gCurrentSelection->CurrentMenu->QuestionId == 0) {\r
+ mCurFakeQestId = Statement->FakeQuestionId;\r
+ } else {\r
+ mCurFakeQestId = 0;\r
+ }\r
+ }\r
+ } else {\r
+ Statement = GetBrowserStatement(UserInput->SelectedStatement);\r
+ ASSERT (Statement != NULL);\r
+\r
+ gCurrentSelection->Statement = Statement;\r
+\r
+ if (ChangeHighlight) {\r
+ //\r
+ // This question is the current user select one,record it and later\r
+ // show it as the highlight question.\r
+ //\r
+ gCurrentSelection->CurrentMenu->QuestionId = Statement->QuestionId;\r
+ //\r
+ // For statement like text, actio, it not has question id.\r
+ // So use FakeQuestionId to save the question.\r
+ //\r
+ if (gCurrentSelection->CurrentMenu->QuestionId == 0) {\r
+ mCurFakeQestId = Statement->FakeQuestionId;\r
+ } else {\r
+ mCurFakeQestId = 0;\r
+ }\r
+ }\r
+\r
+ switch (Statement->Operand) {\r
+ case EFI_IFR_REF_OP:\r
+ Status = ProcessGotoOpCode(Statement, gCurrentSelection);\r
+ break;\r
+ \r
+ case EFI_IFR_ACTION_OP:\r
+ //\r
+ // Process the Config string <ConfigResp>\r
+ //\r
+ Status = ProcessQuestionConfig (gCurrentSelection, Statement);\r
+ break;\r
+ \r
+ case EFI_IFR_RESET_BUTTON_OP:\r
+ //\r
+ // Reset Question to default value specified by DefaultId\r
+ //\r
+ Status = ExtractDefault (gCurrentSelection->FormSet, NULL, Statement->DefaultId, FormSetLevel, GetDefaultForAll, NULL, FALSE);\r
+ break;\r
+\r
+ default:\r
+ switch (Statement->Operand) {\r
+ case EFI_IFR_STRING_OP:\r
+ DeleteString(Statement->HiiValue.Value.string, gCurrentSelection->FormSet->HiiHandle);\r
+ Statement->HiiValue.Value.string = UserInput->InputValue.Value.string;\r
+ CopyMem (Statement->BufferValue, UserInput->InputValue.Buffer, (UINTN) UserInput->InputValue.BufferLen);\r
+ FreePool (UserInput->InputValue.Buffer);\r
+ break;\r
+\r
+ case EFI_IFR_PASSWORD_OP:\r
+ if (UserInput->InputValue.Buffer == NULL) {\r
+ //\r
+ // User not input new password, just return.\r
+ //\r
+ break;\r
+ }\r
+\r
+ DeleteString(Statement->HiiValue.Value.string, gCurrentSelection->FormSet->HiiHandle);\r
+ Statement->HiiValue.Value.string = UserInput->InputValue.Value.string;\r
+ CopyMem (Statement->BufferValue, UserInput->InputValue.Buffer, (UINTN) UserInput->InputValue.BufferLen);\r
+ FreePool (UserInput->InputValue.Buffer);\r
+ //\r
+ // Two password match, send it to Configuration Driver\r
+ //\r
+ if ((Statement->QuestionFlags & EFI_IFR_FLAG_CALLBACK) != 0) {\r
+ PasswordCheck (NULL, UserInput->SelectedStatement, (CHAR16 *) Statement->BufferValue);\r
+ //\r
+ // Clean the value after saved it.\r
+ //\r
+ ZeroMem (Statement->BufferValue, (UINTN) UserInput->InputValue.BufferLen);\r
+ HiiSetString (gCurrentSelection->FormSet->HiiHandle, Statement->HiiValue.Value.string, (CHAR16*)Statement->BufferValue, NULL);\r
+ } else {\r
+ SetQuestionValue (gCurrentSelection->FormSet, gCurrentSelection->Form, Statement, GetSetValueWithHiiDriver);\r
+ }\r
+ break;\r
+\r
+ case EFI_IFR_ORDERED_LIST_OP:\r
+ CopyMem (Statement->BufferValue, UserInput->InputValue.Buffer, UserInput->InputValue.BufferLen);\r
+ break;\r
+\r
+ default:\r
+ CopyMem (&Statement->HiiValue, &UserInput->InputValue, sizeof (EFI_HII_VALUE));\r
+ break;\r
+ }\r
+ if (Statement->Operand != EFI_IFR_PASSWORD_OP) {\r
+ SetQuestionValue (gCurrentSelection->FormSet, gCurrentSelection->Form, Statement, GetSetValueWithEditBuffer);\r
+ }\r
+ break;\r
+ }\r
+ }\r
+\r
+ return Status;\r
+}\r
+\r
+/**\r
\r
- Handle = Selection->Handle;\r
- MenuItemCount = 0;\r
- ArrayEntry = 0;\r
- OutputString = NULL;\r
+ Display form and wait for user to select one menu option, then return it.\r
\r
- UiInitMenu ();\r
+ @retval EFI_SUCESSS This function always return successfully for now.\r
\r
- CopyMem (&LocalScreen, &gScreenDimensions, sizeof (EFI_SCREEN_DESCRIPTOR));\r
+**/\r
+EFI_STATUS\r
+DisplayForm (\r
+ VOID\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ USER_INPUT UserInput;\r
+ FORM_ENTRY_INFO *CurrentMenu;\r
+ BOOLEAN ChangeHighlight;\r
\r
- StringPtr = GetToken (Selection->Form->FormTitle, Handle);\r
+ ZeroMem (&UserInput, sizeof (USER_INPUT));\r
\r
- if (gClassOfVfr != FORMSET_CLASS_FRONT_PAGE) {\r
- gST->ConOut->SetAttribute (gST->ConOut, TITLE_TEXT | TITLE_BACKGROUND);\r
- PrintStringAt (\r
- (LocalScreen.RightColumn + LocalScreen.LeftColumn - GetStringWidth (StringPtr) / 2) / 2,\r
- LocalScreen.TopRow + 1,\r
- StringPtr\r
- );\r
+ //\r
+ // Update the menu history data.\r
+ //\r
+ CurrentMenu = UiFindMenuList (gCurrentSelection->Handle, &gCurrentSelection->FormSetGuid, gCurrentSelection->FormId);\r
+ if (CurrentMenu == NULL) {\r
+ //\r
+ // Current menu not found, add it to the menu tree\r
+ //\r
+ CurrentMenu = UiAddMenuList (gCurrentSelection->Handle, &gCurrentSelection->FormSetGuid,\r
+ gCurrentSelection->FormId, gCurrentSelection->QuestionId);\r
+ ASSERT (CurrentMenu != NULL);\r
}\r
+ gCurrentSelection->CurrentMenu = CurrentMenu;\r
\r
//\r
- // Remove Buffer allocated for StringPtr after it has been used.\r
+ // Find currrent highlight statement.\r
//\r
- FreePool (StringPtr);\r
+ if (gCurrentSelection->QuestionId == 0) {\r
+ //\r
+ // Highlight not specified, fetch it from cached menu\r
+ //\r
+ gCurrentSelection->QuestionId = CurrentMenu->QuestionId;\r
+ }\r
\r
//\r
// Evaluate all the Expressions in this Form\r
//\r
- Status = EvaluateFormExpressions (Selection->FormSet, Selection->Form);\r
+ Status = EvaluateFormExpressions (gCurrentSelection->FormSet, gCurrentSelection->Form);\r
if (EFI_ERROR (Status)) {\r
return Status;\r
}\r
\r
- Selection->FormEditable = FALSE;\r
- Link = GetFirstNode (&Selection->Form->StatementListHead);\r
- while (!IsNull (&Selection->Form->StatementListHead, Link)) {\r
- Statement = FORM_BROWSER_STATEMENT_FROM_LINK (Link);\r
+ UpdateDisplayFormData ();\r
\r
- if (Statement->SuppressExpression != NULL) {\r
- Suppress = Statement->SuppressExpression->Result.Value.b;\r
- } else {\r
- Suppress = FALSE;\r
- }\r
+ //\r
+ // Three possible status maybe return.\r
+ //\r
+ // EFI_INVALID_PARAMETER: The input dimension info is not valid.\r
+ // EFI_NOT_FOUND: The input value for oneof/orderedlist opcode is not valid\r
+ // and an valid value has return.\r
+ // EFI_SUCCESS: Success shows form and get user input in UserInput paramenter.\r
+ //\r
+ Status = mFormDisplay->FormDisplay (&gDisplayFormData, &UserInput);\r
+ if (EFI_ERROR (Status) && Status != EFI_NOT_FOUND) {\r
+ FreeDisplayFormData();\r
+ return Status;\r
+ }\r
\r
- if (Statement->DisableExpression != NULL) {\r
- Suppress = (BOOLEAN) (Suppress || Statement->DisableExpression->Result.Value.b);\r
- }\r
+ //\r
+ // If status is EFI_SUCCESS, means user has change the highlight menu and new user input return.\r
+ // in this case, browser need to change the highlight menu.\r
+ // If status is EFI_NOT_FOUND, means the input DisplayFormData has error for oneof/orderedlist \r
+ // opcode and new valid value has return, browser core need to adjust\r
+ // value for this opcode and shows this form again.\r
+ //\r
+ ChangeHighlight = (Status == EFI_SUCCESS ? TRUE :FALSE);\r
\r
- if (!Suppress) {\r
- StringPtr = GetToken (Statement->Prompt, Handle);\r
+ Status = ProcessUserInput (&UserInput, ChangeHighlight);\r
\r
- Width = GetWidth (Statement, Handle);\r
+ FreeDisplayFormData();\r
\r
- NumberOfLines = 1;\r
- ArrayEntry = 0;\r
- for (; GetLineByWidth (StringPtr, Width, &ArrayEntry, &OutputString) != 0x0000;) {\r
- //\r
- // If there is more string to process print on the next row and increment the Skip value\r
- //\r
- if (StrLen (&StringPtr[ArrayEntry]) != 0) {\r
- NumberOfLines++;\r
- }\r
+ return Status;\r
+}\r
\r
- FreePool (OutputString);\r
- }\r
+/**\r
+ Functions which are registered to receive notification of\r
+ database events have this prototype. The actual event is encoded\r
+ in NotifyType. The following table describes how PackageType,\r
+ PackageGuid, Handle, and Package are used for each of the\r
+ notification types.\r
\r
- //\r
- // We are NOT!! removing this StringPtr buffer via FreePool since it is being used in the menuoptions, we will do\r
- // it in UiFreeMenu.\r
- //\r
- MenuOption = UiAddMenuOption (StringPtr, Selection->Handle, Statement, NumberOfLines, MenuItemCount);\r
- MenuItemCount++;\r
+ @param PackageType Package type of the notification.\r
\r
- if (MenuOption->IsQuestion && !MenuOption->ReadOnly) {\r
- //\r
- // At least one item is not readonly, this Form is considered as editable\r
- //\r
- Selection->FormEditable = TRUE;\r
- }\r
- }\r
+ @param PackageGuid If PackageType is\r
+ EFI_HII_PACKAGE_TYPE_GUID, then this is\r
+ the pointer to the GUID from the Guid\r
+ field of EFI_HII_PACKAGE_GUID_HEADER.\r
+ Otherwise, it must be NULL.\r
\r
- Link = GetNextNode (&Selection->Form->StatementListHead, Link);\r
+ @param Package Points to the package referred to by the\r
+ notification Handle The handle of the package\r
+ list which contains the specified package.\r
+\r
+ @param Handle The HII handle.\r
+\r
+ @param NotifyType The type of change concerning the\r
+ database. See\r
+ EFI_HII_DATABASE_NOTIFY_TYPE.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+FormUpdateNotify (\r
+ IN UINT8 PackageType,\r
+ IN CONST EFI_GUID *PackageGuid,\r
+ IN CONST EFI_HII_PACKAGE_HEADER *Package,\r
+ IN EFI_HII_HANDLE Handle,\r
+ IN EFI_HII_DATABASE_NOTIFY_TYPE NotifyType\r
+ )\r
+{\r
+ mHiiPackageListUpdated = TRUE;\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+ Update the NV flag info for this form set.\r
+\r
+ @param FormSet FormSet data structure.\r
+\r
+**/\r
+BOOLEAN\r
+IsNvUpdateRequiredForFormSet (\r
+ IN FORM_BROWSER_FORMSET *FormSet\r
+ )\r
+{\r
+ LIST_ENTRY *Link;\r
+ FORM_BROWSER_FORM *Form;\r
+ BOOLEAN RetVal;\r
+\r
+ //\r
+ // Not finished question initialization, return FALSE.\r
+ //\r
+ if (!FormSet->QuestionInited) {\r
+ return FALSE;\r
}\r
\r
- Status = UiDisplayMenu (Selection);\r
+ RetVal = FALSE;\r
\r
- UiFreeMenu ();\r
+ Link = GetFirstNode (&FormSet->FormListHead);\r
+ while (!IsNull (&FormSet->FormListHead, Link)) {\r
+ Form = FORM_BROWSER_FORM_FROM_LINK (Link);\r
\r
- return Status;\r
+ RetVal = IsNvUpdateRequiredForForm(Form);\r
+ if (RetVal) {\r
+ break;\r
+ }\r
+\r
+ Link = GetNextNode (&FormSet->FormListHead, Link);\r
+ }\r
+\r
+ return RetVal;\r
}\r
\r
/**\r
- Initialize the HII String Token to the correct values.\r
+ Update the NvUpdateRequired flag for a form.\r
+\r
+ @param Form Form data structure.\r
\r
**/\r
-VOID\r
-InitializeBrowserStrings (\r
- VOID\r
+BOOLEAN\r
+IsNvUpdateRequiredForForm (\r
+ IN FORM_BROWSER_FORM *Form\r
)\r
{\r
- gFunctionNineString = GetToken (STRING_TOKEN (FUNCTION_NINE_STRING), gHiiHandle);\r
- gFunctionTenString = GetToken (STRING_TOKEN (FUNCTION_TEN_STRING), gHiiHandle);\r
- gEnterString = GetToken (STRING_TOKEN (ENTER_STRING), gHiiHandle);\r
- gEnterCommitString = GetToken (STRING_TOKEN (ENTER_COMMIT_STRING), gHiiHandle);\r
- gEnterEscapeString = GetToken (STRING_TOKEN (ENTER_ESCAPE_STRING), gHiiHandle);\r
- gEscapeString = GetToken (STRING_TOKEN (ESCAPE_STRING), gHiiHandle);\r
- gSaveFailed = GetToken (STRING_TOKEN (SAVE_FAILED), gHiiHandle);\r
- gMoveHighlight = GetToken (STRING_TOKEN (MOVE_HIGHLIGHT), gHiiHandle);\r
- gMakeSelection = GetToken (STRING_TOKEN (MAKE_SELECTION), gHiiHandle);\r
- gDecNumericInput = GetToken (STRING_TOKEN (DEC_NUMERIC_INPUT), gHiiHandle);\r
- gHexNumericInput = GetToken (STRING_TOKEN (HEX_NUMERIC_INPUT), gHiiHandle);\r
- gToggleCheckBox = GetToken (STRING_TOKEN (TOGGLE_CHECK_BOX), gHiiHandle);\r
- gPromptForData = GetToken (STRING_TOKEN (PROMPT_FOR_DATA), gHiiHandle);\r
- gPromptForPassword = GetToken (STRING_TOKEN (PROMPT_FOR_PASSWORD), gHiiHandle);\r
- gPromptForNewPassword = GetToken (STRING_TOKEN (PROMPT_FOR_NEW_PASSWORD), gHiiHandle);\r
- gConfirmPassword = GetToken (STRING_TOKEN (CONFIRM_PASSWORD), gHiiHandle);\r
- gConfirmError = GetToken (STRING_TOKEN (CONFIRM_ERROR), gHiiHandle);\r
- gPassowordInvalid = GetToken (STRING_TOKEN (PASSWORD_INVALID), gHiiHandle);\r
- gPressEnter = GetToken (STRING_TOKEN (PRESS_ENTER), gHiiHandle);\r
- gEmptyString = GetToken (STRING_TOKEN (EMPTY_STRING), gHiiHandle);\r
- gAreYouSure = GetToken (STRING_TOKEN (ARE_YOU_SURE), gHiiHandle);\r
- gYesResponse = GetToken (STRING_TOKEN (ARE_YOU_SURE_YES), gHiiHandle);\r
- gNoResponse = GetToken (STRING_TOKEN (ARE_YOU_SURE_NO), gHiiHandle);\r
- gMiniString = GetToken (STRING_TOKEN (MINI_STRING), gHiiHandle);\r
- gPlusString = GetToken (STRING_TOKEN (PLUS_STRING), gHiiHandle);\r
- gMinusString = GetToken (STRING_TOKEN (MINUS_STRING), gHiiHandle);\r
- gAdjustNumber = GetToken (STRING_TOKEN (ADJUST_NUMBER), gHiiHandle);\r
- gSaveChanges = GetToken (STRING_TOKEN (SAVE_CHANGES), gHiiHandle);\r
- gOptionMismatch = GetToken (STRING_TOKEN (OPTION_MISMATCH), gHiiHandle);\r
- gFormSuppress = GetToken (STRING_TOKEN (FORM_SUPPRESSED), gHiiHandle);\r
- return ;\r
+ LIST_ENTRY *Link;\r
+ FORM_BROWSER_STATEMENT *Statement;\r
+\r
+ Link = GetFirstNode (&Form->StatementListHead);\r
+ while (!IsNull (&Form->StatementListHead, Link)) {\r
+ Statement = FORM_BROWSER_STATEMENT_FROM_LINK (Link);\r
+\r
+ if (Statement->ValueChanged) {\r
+ return TRUE;\r
+ }\r
+\r
+ Link = GetNextNode (&Form->StatementListHead, Link);\r
+ }\r
+\r
+ return FALSE;\r
}\r
\r
/**\r
- Free up the resource allocated for all strings required\r
- by Setup Browser.\r
+ Check whether the storage data for current form set is changed.\r
\r
+ @param FormSet FormSet data structure.\r
+\r
+ @retval TRUE Data is changed.\r
+ @retval FALSE Data is not changed.\r
**/\r
-VOID\r
-FreeBrowserStrings (\r
- VOID\r
+BOOLEAN \r
+IsStorageDataChangedForFormSet (\r
+ IN FORM_BROWSER_FORMSET *FormSet\r
)\r
{\r
- FreePool (gFunctionNineString);\r
- FreePool (gFunctionTenString);\r
- FreePool (gEnterString);\r
- FreePool (gEnterCommitString);\r
- FreePool (gEnterEscapeString);\r
- FreePool (gEscapeString);\r
- FreePool (gMoveHighlight);\r
- FreePool (gMakeSelection);\r
- FreePool (gDecNumericInput);\r
- FreePool (gHexNumericInput);\r
- FreePool (gToggleCheckBox);\r
- FreePool (gPromptForData);\r
- FreePool (gPromptForPassword);\r
- FreePool (gPromptForNewPassword);\r
- FreePool (gConfirmPassword);\r
- FreePool (gPassowordInvalid);\r
- FreePool (gConfirmError);\r
- FreePool (gPressEnter);\r
- FreePool (gEmptyString);\r
- FreePool (gAreYouSure);\r
- FreePool (gYesResponse);\r
- FreePool (gNoResponse);\r
- FreePool (gMiniString);\r
- FreePool (gPlusString);\r
- FreePool (gMinusString);\r
- FreePool (gAdjustNumber);\r
- FreePool (gSaveChanges);\r
- FreePool (gOptionMismatch);\r
- FreePool (gFormSuppress);\r
- return ;\r
+ LIST_ENTRY *Link;\r
+ FORMSET_STORAGE *Storage;\r
+ BROWSER_STORAGE *BrowserStorage;\r
+ CHAR16 *ConfigRespNew;\r
+ CHAR16 *ConfigRespOld;\r
+ BOOLEAN RetVal;\r
+\r
+ RetVal = FALSE;\r
+ ConfigRespNew = NULL;\r
+ ConfigRespOld = NULL;\r
+\r
+ //\r
+ // Request current settings from Configuration Driver\r
+ //\r
+ Link = GetFirstNode (&FormSet->StorageListHead);\r
+ while (!IsNull (&FormSet->StorageListHead, Link)) {\r
+ Storage = FORMSET_STORAGE_FROM_LINK (Link);\r
+ Link = GetNextNode (&FormSet->StorageListHead, Link);\r
+\r
+ BrowserStorage = Storage->BrowserStorage;\r
+\r
+ if (BrowserStorage->Type == EFI_HII_VARSTORE_EFI_VARIABLE) {\r
+ continue;\r
+ }\r
+\r
+ if (Storage->ElementCount == 0) {\r
+ continue;\r
+ }\r
+\r
+ StorageToConfigResp (BrowserStorage, &ConfigRespNew, Storage->ConfigRequest, TRUE);\r
+ StorageToConfigResp (BrowserStorage, &ConfigRespOld, Storage->ConfigRequest, FALSE);\r
+ ASSERT (ConfigRespNew != NULL && ConfigRespOld != NULL);\r
+\r
+ if (StrCmp (ConfigRespNew, ConfigRespOld) != 0) {\r
+ RetVal = TRUE;\r
+ }\r
+\r
+ FreePool (ConfigRespNew);\r
+ ConfigRespNew = NULL;\r
+\r
+ FreePool (ConfigRespOld);\r
+ ConfigRespOld = NULL;\r
+\r
+ if (RetVal) {\r
+ break;\r
+ }\r
+ }\r
+\r
+ return RetVal;\r
}\r
\r
+/**\r
+ Find menu which will show next time.\r
+\r
+ @param Selection On input, Selection tell setup browser the information\r
+ about the Selection, form and formset to be displayed.\r
+ On output, Selection return the screen item that is selected\r
+ by user.\r
+ @param SettingLevel Input Settting level, if it is FormLevel, just exit current form. \r
+ else, we need to exit current formset.\r
+ \r
+ @retval TRUE Exit current form.\r
+ @retval FALSE User press ESC and keep in current form.\r
+**/\r
+BOOLEAN\r
+FindNextMenu (\r
+ IN OUT UI_MENU_SELECTION *Selection,\r
+ IN BROWSER_SETTING_SCOPE SettingLevel\r
+ )\r
+{\r
+ FORM_ENTRY_INFO *CurrentMenu;\r
+ FORM_ENTRY_INFO *ParentMenu;\r
+ BROWSER_SETTING_SCOPE Scope;\r
+ \r
+ CurrentMenu = Selection->CurrentMenu;\r
+ ParentMenu = NULL;\r
+ Scope = FormSetLevel;\r
+\r
+ if (CurrentMenu != NULL && (ParentMenu = UiFindParentMenu(CurrentMenu)) != NULL) {\r
+ //\r
+ // we have a parent, so go to the parent menu\r
+ //\r
+ if (CompareGuid (&CurrentMenu->FormSetGuid, &ParentMenu->FormSetGuid)) {\r
+ if (SettingLevel == FormSetLevel) {\r
+ //\r
+ // Find a menu which has different formset guid with current.\r
+ //\r
+ while (CompareGuid (&CurrentMenu->FormSetGuid, &ParentMenu->FormSetGuid)) {\r
+ CurrentMenu = ParentMenu;\r
+ if ((ParentMenu = UiFindParentMenu(CurrentMenu)) == NULL) {\r
+ break;\r
+ }\r
+ }\r
+\r
+ if (ParentMenu != NULL) {\r
+ Scope = FormSetLevel;\r
+ }\r
+ } else {\r
+ Scope = FormLevel;\r
+ }\r
+ } else {\r
+ Scope = FormSetLevel;\r
+ }\r
+ }\r
+\r
+ //\r
+ // Form Level Check whether the data is changed.\r
+ //\r
+ if ((gBrowserSettingScope == FormLevel && IsNvUpdateRequiredForForm (Selection->Form)) ||\r
+ (gBrowserSettingScope == FormSetLevel && IsNvUpdateRequiredForFormSet(Selection->FormSet) && Scope == FormSetLevel)) {\r
+ if (!ProcessChangedData(Selection, Scope)) {\r
+ return FALSE;\r
+ }\r
+ }\r
+\r
+ if (ParentMenu != NULL) {\r
+ //\r
+ // ParentMenu is found. Then, go to it.\r
+ //\r
+ if (Scope == FormLevel) {\r
+ Selection->Action = UI_ACTION_REFRESH_FORM;\r
+ } else {\r
+ Selection->Action = UI_ACTION_REFRESH_FORMSET;\r
+ CopyMem (&Selection->FormSetGuid, &ParentMenu->FormSetGuid, sizeof (EFI_GUID));\r
+ Selection->Handle = ParentMenu->HiiHandle;\r
+ }\r
+\r
+ Selection->Statement = NULL;\r
+\r
+ Selection->FormId = ParentMenu->FormId;\r
+ Selection->QuestionId = ParentMenu->QuestionId;\r
+\r
+ //\r
+ // Clear highlight record for this menu\r
+ //\r
+ CurrentMenu->QuestionId = 0;\r
+ return FALSE;\r
+ }\r
+\r
+ //\r
+ // Current in root page, exit the SendForm\r
+ //\r
+ Selection->Action = UI_ACTION_EXIT;\r
+\r
+ return TRUE;\r
+}\r
\r
/**\r
- Update key's help imformation.\r
-\r
- @param Selection Tell setup browser the information about the Selection\r
- @param MenuOption The Menu option\r
- @param Selected Whether or not a tag be selected\r
-\r
+ Call the call back function for the question and process the return action.\r
+\r
+ @param Selection On input, Selection tell setup browser the information\r
+ about the Selection, form and formset to be displayed.\r
+ On output, Selection return the screen item that is selected\r
+ by user.\r
+ @param Question The Question which need to call.\r
+ @param Action The action request.\r
+ @param SkipSaveOrDiscard Whether skip save or discard action.\r
+\r
+ @retval EFI_SUCCESS The call back function excutes successfully.\r
+ @return Other value if the call back function failed to excute. \r
**/\r
-VOID\r
-UpdateKeyHelp (\r
- IN UI_MENU_SELECTION *Selection,\r
- IN UI_MENU_OPTION *MenuOption,\r
- IN BOOLEAN Selected\r
+EFI_STATUS \r
+ProcessCallBackFunction (\r
+ IN OUT UI_MENU_SELECTION *Selection,\r
+ IN FORM_BROWSER_STATEMENT *Question,\r
+ IN EFI_BROWSER_ACTION Action,\r
+ IN BOOLEAN SkipSaveOrDiscard\r
)\r
{\r
- UINTN SecCol;\r
- UINTN ThdCol;\r
- UINTN LeftColumnOfHelp;\r
- UINTN RightColumnOfHelp;\r
- UINTN TopRowOfHelp;\r
- UINTN BottomRowOfHelp;\r
- UINTN StartColumnOfHelp;\r
- EFI_SCREEN_DESCRIPTOR LocalScreen;\r
- FORM_BROWSER_STATEMENT *Statement;\r
-\r
- CopyMem (&LocalScreen, &gScreenDimensions, sizeof (EFI_SCREEN_DESCRIPTOR));\r
-\r
- SecCol = LocalScreen.LeftColumn + (LocalScreen.RightColumn - LocalScreen.LeftColumn) / 3;\r
- ThdCol = LocalScreen.LeftColumn + (LocalScreen.RightColumn - LocalScreen.LeftColumn) * 2 / 3;\r
+ EFI_STATUS Status;\r
+ EFI_BROWSER_ACTION_REQUEST ActionRequest;\r
+ EFI_HII_CONFIG_ACCESS_PROTOCOL *ConfigAccess;\r
+ EFI_HII_VALUE *HiiValue;\r
+ EFI_IFR_TYPE_VALUE *TypeValue;\r
+ FORM_BROWSER_STATEMENT *Statement;\r
+ BOOLEAN SubmitFormIsRequired;\r
+ BOOLEAN DiscardFormIsRequired;\r
+ BOOLEAN NeedExit;\r
+ LIST_ENTRY *Link;\r
+ BROWSER_SETTING_SCOPE SettingLevel;\r
\r
- StartColumnOfHelp = LocalScreen.LeftColumn + 2;\r
- LeftColumnOfHelp = LocalScreen.LeftColumn + 1;\r
- RightColumnOfHelp = LocalScreen.RightColumn - 2;\r
- TopRowOfHelp = LocalScreen.BottomRow - 4;\r
- BottomRowOfHelp = LocalScreen.BottomRow - 3;\r
+ ConfigAccess = Selection->FormSet->ConfigAccess;\r
+ SubmitFormIsRequired = FALSE;\r
+ SettingLevel = FormSetLevel;\r
+ DiscardFormIsRequired = FALSE;\r
+ NeedExit = FALSE;\r
+ Status = EFI_SUCCESS;\r
+ ActionRequest = EFI_BROWSER_ACTION_REQUEST_NONE;\r
+\r
+ if (ConfigAccess == NULL) {\r
+ return EFI_SUCCESS;\r
+ }\r
\r
- gST->ConOut->SetAttribute (gST->ConOut, KEYHELP_TEXT | KEYHELP_BACKGROUND);\r
+ Link = GetFirstNode (&Selection->Form->StatementListHead);\r
+ while (!IsNull (&Selection->Form->StatementListHead, Link)) {\r
+ Statement = FORM_BROWSER_STATEMENT_FROM_LINK (Link);\r
+ Link = GetNextNode (&Selection->Form->StatementListHead, Link);\r
\r
- Statement = MenuOption->ThisTag;\r
- switch (Statement->Operand) {\r
- case EFI_IFR_ORDERED_LIST_OP:\r
- case EFI_IFR_ONE_OF_OP:\r
- case EFI_IFR_NUMERIC_OP:\r
- case EFI_IFR_TIME_OP:\r
- case EFI_IFR_DATE_OP:\r
- ClearLines (LeftColumnOfHelp, RightColumnOfHelp, TopRowOfHelp, BottomRowOfHelp, KEYHELP_TEXT | KEYHELP_BACKGROUND);\r
-\r
- if (!Selected) {\r
- if (gClassOfVfr == FORMSET_CLASS_PLATFORM_SETUP) {\r
- if (Selection->FormEditable) {\r
- PrintStringAt (SecCol, TopRowOfHelp, gFunctionNineString);\r
- PrintStringAt (ThdCol, TopRowOfHelp, gFunctionTenString);\r
- }\r
- PrintStringAt (ThdCol, BottomRowOfHelp, gEscapeString);\r
- }\r
+ //\r
+ // if Question != NULL, only process the question. Else, process all question in this form.\r
+ //\r
+ if ((Question != NULL) && (Statement != Question)) {\r
+ continue;\r
+ }\r
+ \r
+ if ((Statement->QuestionFlags & EFI_IFR_FLAG_CALLBACK) != EFI_IFR_FLAG_CALLBACK) {\r
+ continue;\r
+ }\r
\r
- if ((Statement->Operand == EFI_IFR_DATE_OP) ||\r
- (Statement->Operand == EFI_IFR_TIME_OP)) {\r
- PrintAt (\r
- StartColumnOfHelp,\r
- BottomRowOfHelp,\r
- L"%c%c%c%c%s",\r
- ARROW_UP,\r
- ARROW_DOWN,\r
- ARROW_RIGHT,\r
- ARROW_LEFT,\r
- gMoveHighlight\r
- );\r
- PrintStringAt (SecCol, BottomRowOfHelp, gAdjustNumber);\r
- } else {\r
- PrintAt (StartColumnOfHelp, BottomRowOfHelp, L"%c%c%s", ARROW_UP, ARROW_DOWN, gMoveHighlight);\r
- if (Statement->Operand == EFI_IFR_NUMERIC_OP && Statement->Step != 0) {\r
- PrintStringAt (SecCol, BottomRowOfHelp, gAdjustNumber);\r
- } else {\r
- PrintStringAt (SecCol, BottomRowOfHelp, gEnterString);\r
- }\r
+ //\r
+ // Check whether Statement is disabled.\r
+ //\r
+ if (Statement->Expression != NULL) {\r
+ if (EvaluateExpressionList(Statement->Expression, TRUE, Selection->FormSet, Selection->Form) == ExpressDisable) {\r
+ continue;\r
}\r
- } else {\r
- PrintStringAt (SecCol, BottomRowOfHelp, gEnterCommitString);\r
+ }\r
\r
+ HiiValue = &Statement->HiiValue;\r
+ TypeValue = &HiiValue->Value;\r
+ if (HiiValue->Type == EFI_IFR_TYPE_BUFFER) {\r
//\r
- // If it is a selected numeric with manual input, display different message\r
+ // For OrderedList, passing in the value buffer to Callback()\r
//\r
- if ((Statement->Operand == EFI_IFR_NUMERIC_OP) && (Statement->Step == 0)) {\r
- PrintStringAt (\r
- SecCol,\r
- TopRowOfHelp,\r
- ((Statement->Flags & EFI_IFR_DISPLAY_UINT_HEX) == EFI_IFR_DISPLAY_UINT_HEX) ? gHexNumericInput : gDecNumericInput\r
- );\r
- } else if (Statement->Operand != EFI_IFR_ORDERED_LIST_OP) {\r
- PrintAt (StartColumnOfHelp, BottomRowOfHelp, L"%c%c%s", ARROW_UP, ARROW_DOWN, gMoveHighlight);\r
- }\r
+ TypeValue = (EFI_IFR_TYPE_VALUE *) Statement->BufferValue;\r
+ }\r
+ \r
+ ActionRequest = EFI_BROWSER_ACTION_REQUEST_NONE;\r
+ Status = ConfigAccess->Callback (\r
+ ConfigAccess,\r
+ Action,\r
+ Statement->QuestionId,\r
+ HiiValue->Type,\r
+ TypeValue,\r
+ &ActionRequest\r
+ );\r
+ if (!EFI_ERROR (Status)) {\r
+ //\r
+ // Only for EFI_BROWSER_ACTION_CHANGED need to handle this ActionRequest.\r
+ //\r
+ if (Action == EFI_BROWSER_ACTION_CHANGED) {\r
+ switch (ActionRequest) {\r
+ case EFI_BROWSER_ACTION_REQUEST_RESET:\r
+ DiscardFormIsRequired = TRUE;\r
+ gResetRequired = TRUE;\r
+ NeedExit = TRUE;\r
+ break;\r
\r
- if (Statement->Operand == EFI_IFR_ORDERED_LIST_OP) {\r
- PrintStringAt (StartColumnOfHelp, TopRowOfHelp, gPlusString);\r
- PrintStringAt (ThdCol, TopRowOfHelp, gMinusString);\r
- }\r
+ case EFI_BROWSER_ACTION_REQUEST_SUBMIT:\r
+ SubmitFormIsRequired = TRUE;\r
+ NeedExit = TRUE;\r
+ break;\r
\r
- PrintStringAt (ThdCol, BottomRowOfHelp, gEnterEscapeString);\r
- }\r
- break;\r
+ case EFI_BROWSER_ACTION_REQUEST_EXIT:\r
+ DiscardFormIsRequired = TRUE;\r
+ NeedExit = TRUE;\r
+ break;\r
\r
- case EFI_IFR_CHECKBOX_OP:\r
- ClearLines (LeftColumnOfHelp, RightColumnOfHelp, TopRowOfHelp, BottomRowOfHelp, KEYHELP_TEXT | KEYHELP_BACKGROUND);\r
+ case EFI_BROWSER_ACTION_REQUEST_FORM_SUBMIT_EXIT:\r
+ SubmitFormIsRequired = TRUE;\r
+ SettingLevel = FormLevel;\r
+ NeedExit = TRUE;\r
+ break;\r
\r
- if (gClassOfVfr == FORMSET_CLASS_PLATFORM_SETUP) {\r
- if (Selection->FormEditable) {\r
- PrintStringAt (SecCol, TopRowOfHelp, gFunctionNineString);\r
- PrintStringAt (ThdCol, TopRowOfHelp, gFunctionTenString);\r
- }\r
- PrintStringAt (ThdCol, BottomRowOfHelp, gEscapeString);\r
- }\r
+ case EFI_BROWSER_ACTION_REQUEST_FORM_DISCARD_EXIT:\r
+ DiscardFormIsRequired = TRUE;\r
+ SettingLevel = FormLevel;\r
+ NeedExit = TRUE;\r
+ break;\r
\r
- PrintAt (StartColumnOfHelp, BottomRowOfHelp, L"%c%c%s", ARROW_UP, ARROW_DOWN, gMoveHighlight);\r
- PrintStringAt (SecCol, BottomRowOfHelp, gToggleCheckBox);\r
- break;\r
+ case EFI_BROWSER_ACTION_REQUEST_FORM_APPLY:\r
+ SubmitFormIsRequired = TRUE;\r
+ SettingLevel = FormLevel;\r
+ break;\r
+\r
+ case EFI_BROWSER_ACTION_REQUEST_FORM_DISCARD:\r
+ DiscardFormIsRequired = TRUE;\r
+ SettingLevel = FormLevel;\r
+ break;\r
\r
- case EFI_IFR_REF_OP:\r
- case EFI_IFR_PASSWORD_OP:\r
- case EFI_IFR_STRING_OP:\r
- case EFI_IFR_TEXT_OP:\r
- case EFI_IFR_ACTION_OP:\r
- case EFI_IFR_RESET_BUTTON_OP:\r
- ClearLines (LeftColumnOfHelp, RightColumnOfHelp, TopRowOfHelp, BottomRowOfHelp, KEYHELP_TEXT | KEYHELP_BACKGROUND);\r
-\r
- if (!Selected) {\r
- if (gClassOfVfr == FORMSET_CLASS_PLATFORM_SETUP) {\r
- if (Selection->FormEditable) {\r
- PrintStringAt (SecCol, TopRowOfHelp, gFunctionNineString);\r
- PrintStringAt (ThdCol, TopRowOfHelp, gFunctionTenString);\r
+ default:\r
+ break;\r
}\r
- PrintStringAt (ThdCol, BottomRowOfHelp, gEscapeString);\r
}\r
\r
- PrintAt (StartColumnOfHelp, BottomRowOfHelp, L"%c%c%s", ARROW_UP, ARROW_DOWN, gMoveHighlight);\r
- if (Statement->Operand != EFI_IFR_TEXT_OP) {\r
- PrintStringAt (SecCol, BottomRowOfHelp, gEnterString);\r
+ //\r
+ // According the spec, return value from call back of "changing" and \r
+ // "retrieve" should update to the question's temp buffer.\r
+ //\r
+ if (Action == EFI_BROWSER_ACTION_CHANGING || Action == EFI_BROWSER_ACTION_RETRIEVE) {\r
+ SetQuestionValue(Selection->FormSet, Selection->Form, Statement, GetSetValueWithEditBuffer);\r
}\r
} else {\r
- if (Statement->Operand != EFI_IFR_REF_OP) {\r
- PrintStringAt (\r
- (LocalScreen.RightColumn - GetStringWidth (gEnterCommitString) / 2) / 2,\r
- BottomRowOfHelp,\r
- gEnterCommitString\r
- );\r
- PrintStringAt (ThdCol, BottomRowOfHelp, gEnterEscapeString);\r
+ //\r
+ // According the spec, return fail from call back of "changing" and \r
+ // "retrieve", should restore the question's value.\r
+ //\r
+ if (Action == EFI_BROWSER_ACTION_CHANGING || Action == EFI_BROWSER_ACTION_RETRIEVE) {\r
+ GetQuestionValue(Selection->FormSet, Selection->Form, Statement, GetSetValueWithEditBuffer);\r
}\r
- }\r
- break;\r
\r
- default:\r
- break;\r
+ if (Status == EFI_UNSUPPORTED) {\r
+ //\r
+ // If return EFI_UNSUPPORTED, also consider Hii driver suceess deal with it.\r
+ //\r
+ Status = EFI_SUCCESS;\r
+ }\r
+ }\r
}\r
-}\r
\r
-/**\r
- Functions which are registered to receive notification of\r
- database events have this prototype. The actual event is encoded\r
- in NotifyType. The following table describes how PackageType,\r
- PackageGuid, Handle, and Package are used for each of the\r
- notification types.\r
+ if (SubmitFormIsRequired && !SkipSaveOrDiscard) {\r
+ SubmitForm (Selection->FormSet, Selection->Form, SettingLevel);\r
+ }\r
\r
- @param PackageType Package type of the notification.\r
+ if (DiscardFormIsRequired && !SkipSaveOrDiscard) {\r
+ DiscardForm (Selection->FormSet, Selection->Form, SettingLevel);\r
+ }\r
\r
- @param PackageGuid If PackageType is\r
- EFI_HII_PACKAGE_TYPE_GUID, then this is\r
- the pointer to the GUID from the Guid\r
- field of EFI_HII_PACKAGE_GUID_HEADER.\r
- Otherwise, it must be NULL.\r
+ if (NeedExit) {\r
+ FindNextMenu (Selection, SettingLevel);\r
+ }\r
\r
- @param Package Points to the package referred to by the\r
- notification Handle The handle of the package\r
- list which contains the specified package.\r
+ return Status;\r
+}\r
\r
- @param Handle The HII handle.\r
+/**\r
+ Call the retrieve type call back function for one question to get the initialize data.\r
+ \r
+ This function only used when in the initialize stage, because in this stage, the \r
+ Selection->Form is not ready. For other case, use the ProcessCallBackFunction instead.\r
\r
- @param NotifyType The type of change concerning the\r
- database. See\r
- EFI_HII_DATABASE_NOTIFY_TYPE.\r
+ @param ConfigAccess The config access protocol produced by the hii driver.\r
+ @param Statement The Question which need to call.\r
\r
+ @retval EFI_SUCCESS The call back function excutes successfully.\r
+ @return Other value if the call back function failed to excute. \r
**/\r
-EFI_STATUS\r
-EFIAPI\r
-FormUpdateNotify (\r
- IN UINT8 PackageType,\r
- IN CONST EFI_GUID *PackageGuid,\r
- IN CONST EFI_HII_PACKAGE_HEADER *Package,\r
- IN EFI_HII_HANDLE Handle,\r
- IN EFI_HII_DATABASE_NOTIFY_TYPE NotifyType\r
+EFI_STATUS \r
+ProcessRetrieveForQuestion (\r
+ IN EFI_HII_CONFIG_ACCESS_PROTOCOL *ConfigAccess,\r
+ IN FORM_BROWSER_STATEMENT *Statement\r
)\r
{\r
- mHiiPackageListUpdated = TRUE;\r
+ EFI_STATUS Status;\r
+ EFI_BROWSER_ACTION_REQUEST ActionRequest;\r
+ EFI_HII_VALUE *HiiValue;\r
+ EFI_IFR_TYPE_VALUE *TypeValue;\r
\r
- return EFI_SUCCESS;\r
+ Status = EFI_SUCCESS;\r
+ ActionRequest = EFI_BROWSER_ACTION_REQUEST_NONE;\r
+ \r
+ if ((Statement->QuestionFlags & EFI_IFR_FLAG_CALLBACK) != EFI_IFR_FLAG_CALLBACK) {\r
+ return EFI_UNSUPPORTED;\r
+ }\r
+\r
+ HiiValue = &Statement->HiiValue;\r
+ TypeValue = &HiiValue->Value;\r
+ if (HiiValue->Type == EFI_IFR_TYPE_BUFFER) {\r
+ //\r
+ // For OrderedList, passing in the value buffer to Callback()\r
+ //\r
+ TypeValue = (EFI_IFR_TYPE_VALUE *) Statement->BufferValue;\r
+ }\r
+ \r
+ ActionRequest = EFI_BROWSER_ACTION_REQUEST_NONE;\r
+ Status = ConfigAccess->Callback (\r
+ ConfigAccess,\r
+ EFI_BROWSER_ACTION_RETRIEVE,\r
+ Statement->QuestionId,\r
+ HiiValue->Type,\r
+ TypeValue,\r
+ &ActionRequest\r
+ );\r
+ return Status;\r
}\r
\r
/**\r
{\r
EFI_STATUS Status;\r
LIST_ENTRY *Link;\r
- EFI_BROWSER_ACTION_REQUEST ActionRequest;\r
EFI_HANDLE NotifyHandle;\r
- EFI_HII_VALUE *HiiValue;\r
FORM_BROWSER_STATEMENT *Statement;\r
EFI_HII_CONFIG_ACCESS_PROTOCOL *ConfigAccess;\r
- FORM_BROWSER_FORMSET *FormSet;\r
- EFI_INPUT_KEY Key;\r
\r
- gMenuRefreshHead = NULL;\r
- gResetRequired = FALSE;\r
- FormSet = Selection->FormSet;\r
+ ConfigAccess = Selection->FormSet->ConfigAccess;\r
\r
//\r
// Register notify for Form package update\r
}\r
\r
//\r
- // Before display the formset, invoke ConfigAccess.Callback() with EFI_BROWSER_ACTION_FORM_OPEN\r
+ // Initialize current settings of Questions in this FormSet\r
//\r
- ConfigAccess = Selection->FormSet->ConfigAccess;\r
- if ((ConfigAccess != NULL) && (Selection->Action != UI_ACTION_REFRESH_FORMSET)) {\r
- ActionRequest = EFI_BROWSER_ACTION_REQUEST_NONE;\r
- mHiiPackageListUpdated = FALSE;\r
- Status = ConfigAccess->Callback (\r
- ConfigAccess,\r
- EFI_BROWSER_ACTION_FORM_OPEN,\r
- 0,\r
- EFI_IFR_TYPE_UNDEFINED,\r
- NULL,\r
- &ActionRequest\r
- );\r
-\r
- if (!EFI_ERROR (Status)) {\r
- switch (ActionRequest) {\r
- case EFI_BROWSER_ACTION_REQUEST_RESET:\r
- gResetRequired = TRUE;\r
- break;\r
+ InitializeCurrentSetting (Selection->FormSet);\r
\r
- case EFI_BROWSER_ACTION_REQUEST_SUBMIT:\r
- //\r
- // Till now there is no uncommitted data, so ignore this request\r
- //\r
- break;\r
-\r
- case EFI_BROWSER_ACTION_REQUEST_EXIT:\r
- Selection->Action = UI_ACTION_EXIT;\r
- break;\r
+ //\r
+ // Initilize Action field.\r
+ //\r
+ Selection->Action = UI_ACTION_REFRESH_FORM;\r
\r
- default:\r
- break;\r
- }\r
- }\r
+ //\r
+ // Clean the mCurFakeQestId value is formset refreshed.\r
+ //\r
+ mCurFakeQestId = 0;\r
\r
+ do {\r
+ //\r
+ // IFR is updated, force to reparse the IFR binary\r
+ //\r
if (mHiiPackageListUpdated) {\r
- //\r
- // IFR is updated during callback, force to reparse the IFR binary\r
- //\r
- mHiiPackageListUpdated = FALSE;\r
Selection->Action = UI_ACTION_REFRESH_FORMSET;\r
- goto Done;\r
+ mHiiPackageListUpdated = FALSE;\r
+ break;\r
}\r
- }\r
\r
- //\r
- // Initialize current settings of Questions in this FormSet\r
- //\r
- Status = InitializeCurrentSetting (Selection->FormSet);\r
- if (EFI_ERROR (Status)) {\r
- Selection->Action = UI_ACTION_EXIT;\r
- goto Done;\r
- }\r
-\r
- do {\r
//\r
// Initialize Selection->Form\r
//\r
//\r
// No Form to display\r
//\r
- return EFI_NOT_FOUND;\r
+ Status = EFI_NOT_FOUND;\r
+ goto Done;\r
}\r
\r
//\r
// Check Form is suppressed.\r
//\r
if (Selection->Form->SuppressExpression != NULL) {\r
- Status = EvaluateExpression (Selection->FormSet, Selection->Form, Selection->Form->SuppressExpression);\r
- if (EFI_ERROR (Status)) {\r
- return Status;\r
- }\r
-\r
- if (Selection->Form->SuppressExpression->Result.Value.b) {\r
+ if (EvaluateExpressionList(Selection->Form->SuppressExpression, TRUE, Selection->FormSet, Selection->Form) == ExpressSuppress) {\r
//\r
// Form is suppressed. \r
//\r
- do {\r
- CreateDialog (4, TRUE, 0, NULL, &Key, gEmptyString, gFormSuppress, gPressEnter, gEmptyString);\r
- } while (Key.UnicodeChar != CHAR_CARRIAGE_RETURN);\r
+ gBrowserStatus = BROWSER_FORM_SUPPRESS;\r
+ Status = EFI_NOT_FOUND;\r
+ goto Done;\r
+ }\r
+ }\r
+\r
+ //\r
+ // Before display new form, invoke ConfigAccess.Callback() with EFI_BROWSER_ACTION_FORM_OPEN\r
+ // for each question with callback flag.\r
+ // New form may be the first form, or the different form after another form close.\r
+ //\r
+ if ((ConfigAccess != NULL) &&\r
+ ((Selection->Handle != mCurrentHiiHandle) ||\r
+ (!CompareGuid (&Selection->FormSetGuid, &mCurrentFormSetGuid)) ||\r
+ (Selection->FormId != mCurrentFormId))) {\r
+ //\r
+ // Keep current form information\r
+ //\r
+ mCurrentHiiHandle = Selection->Handle;\r
+ CopyGuid (&mCurrentFormSetGuid, &Selection->FormSetGuid);\r
+ mCurrentFormId = Selection->FormId;\r
+\r
+ Status = ProcessCallBackFunction (Selection, NULL, EFI_BROWSER_ACTION_FORM_OPEN, FALSE);\r
+ if (EFI_ERROR (Status)) {\r
+ goto Done;\r
+ }\r
\r
- return EFI_NOT_FOUND;\r
+ //\r
+ // IFR is updated during callback of open form, force to reparse the IFR binary\r
+ //\r
+ if (mHiiPackageListUpdated) {\r
+ Selection->Action = UI_ACTION_REFRESH_FORMSET;\r
+ mHiiPackageListUpdated = FALSE;\r
+ break;\r
}\r
}\r
- \r
+\r
//\r
// Load Questions' Value for display\r
//\r
- Status = LoadFormSetConfig (Selection->FormSet);\r
+ Status = LoadFormSetConfig (Selection, Selection->FormSet);\r
if (EFI_ERROR (Status)) {\r
- return Status;\r
+ goto Done;\r
}\r
\r
//\r
- // Displays the Header and Footer borders\r
+ // IFR is updated during callback of read value, force to reparse the IFR binary\r
//\r
- DisplayPageFrame ();\r
+ if (mHiiPackageListUpdated) {\r
+ Selection->Action = UI_ACTION_REFRESH_FORMSET;\r
+ mHiiPackageListUpdated = FALSE;\r
+ break;\r
+ }\r
\r
//\r
// Display form\r
//\r
- Status = DisplayForm (Selection);\r
+ Status = DisplayForm ();\r
if (EFI_ERROR (Status)) {\r
- return Status;\r
+ goto Done;\r
}\r
\r
//\r
//\r
Statement = Selection->Statement;\r
if (Statement != NULL) {\r
- if ((Statement->QuestionFlags & EFI_IFR_FLAG_RESET_REQUIRED) == EFI_IFR_FLAG_RESET_REQUIRED) {\r
- gResetRequired = TRUE;\r
- }\r
-\r
- //\r
- // Reset FormPackage update flag\r
- //\r
- mHiiPackageListUpdated = FALSE;\r
-\r
- if (((Statement->QuestionFlags & EFI_IFR_FLAG_CALLBACK) == EFI_IFR_FLAG_CALLBACK) && (Statement->Operand != EFI_IFR_PASSWORD_OP)) {\r
- ActionRequest = EFI_BROWSER_ACTION_REQUEST_NONE;\r
-\r
- HiiValue = &Statement->HiiValue;\r
- if (HiiValue->Type == EFI_IFR_TYPE_STRING) {\r
- //\r
- // Create String in HII database for Configuration Driver to retrieve\r
- //\r
- HiiValue->Value.string = NewString ((CHAR16 *) Statement->BufferValue, Selection->FormSet->HiiHandle);\r
- }\r
-\r
- if (ConfigAccess == NULL) {\r
- return EFI_UNSUPPORTED;\r
- }\r
- Status = ConfigAccess->Callback (\r
- ConfigAccess,\r
- EFI_BROWSER_ACTION_CHANGING,\r
- Statement->QuestionId,\r
- HiiValue->Type,\r
- &HiiValue->Value,\r
- &ActionRequest\r
- );\r
-\r
- if (HiiValue->Type == EFI_IFR_TYPE_STRING) {\r
+ if ((ConfigAccess != NULL) && \r
+ ((Statement->QuestionFlags & EFI_IFR_FLAG_CALLBACK) == EFI_IFR_FLAG_CALLBACK) && \r
+ (Statement->Operand != EFI_IFR_PASSWORD_OP)) {\r
+ Status = ProcessCallBackFunction(Selection, Statement, EFI_BROWSER_ACTION_CHANGING, FALSE);\r
+ if (Statement->Operand == EFI_IFR_REF_OP) {\r
//\r
- // Clean the String in HII Database\r
+ // Process dynamic update ref opcode.\r
//\r
- DeleteString (HiiValue->Value.string, Selection->FormSet->HiiHandle);\r
- }\r
-\r
- if (!EFI_ERROR (Status)) {\r
- switch (ActionRequest) {\r
- case EFI_BROWSER_ACTION_REQUEST_RESET:\r
- gResetRequired = TRUE;\r
- break;\r
-\r
- case EFI_BROWSER_ACTION_REQUEST_SUBMIT:\r
- SubmitForm (Selection->FormSet, Selection->Form);\r
- break;\r
-\r
- case EFI_BROWSER_ACTION_REQUEST_EXIT:\r
- Selection->Action = UI_ACTION_EXIT;\r
- gNvUpdateRequired = FALSE;\r
- break;\r
-\r
- default:\r
- break;\r
+ if (!EFI_ERROR (Status)) {\r
+ Status = ProcessGotoOpCode(Statement, Selection);\r
}\r
- } else if (Status != EFI_UNSUPPORTED) {\r
+ \r
//\r
- // Callback return error status other than EFI_UNSUPPORTED\r
+ // Callback return error status or status return from process goto opcode.\r
//\r
- if (Statement->Operand == EFI_IFR_REF_OP) {\r
+ if (EFI_ERROR (Status)) {\r
//\r
// Cross reference will not be taken\r
//\r
Selection->QuestionId = 0;\r
}\r
}\r
- }\r
\r
- //\r
- // Check whether Form Package has been updated during Callback\r
- //\r
- if (mHiiPackageListUpdated && (Selection->Action == UI_ACTION_REFRESH_FORM)) {\r
- //\r
- // Force to reparse IFR binary of target Formset\r
- //\r
- mHiiPackageListUpdated = FALSE;\r
- Selection->Action = UI_ACTION_REFRESH_FORMSET;\r
+ if (!EFI_ERROR (Status) && Statement->Operand != EFI_IFR_REF_OP) {\r
+ ProcessCallBackFunction(Selection, Statement, EFI_BROWSER_ACTION_CHANGED, FALSE);\r
+ }\r
}\r
}\r
- } while (Selection->Action == UI_ACTION_REFRESH_FORM);\r
-\r
- //\r
- // Before exit the formset, invoke ConfigAccess.Callback() with EFI_BROWSER_ACTION_FORM_CLOSE\r
- //\r
- if ((ConfigAccess != NULL) && (Selection->Action == UI_ACTION_EXIT)) {\r
- ActionRequest = EFI_BROWSER_ACTION_REQUEST_NONE;\r
- Status = ConfigAccess->Callback (\r
- ConfigAccess,\r
- EFI_BROWSER_ACTION_FORM_CLOSE,\r
- 0,\r
- EFI_IFR_TYPE_UNDEFINED,\r
- NULL,\r
- &ActionRequest\r
- );\r
\r
- if (!EFI_ERROR (Status)) {\r
- switch (ActionRequest) {\r
- case EFI_BROWSER_ACTION_REQUEST_RESET:\r
- gResetRequired = TRUE;\r
- break;\r
-\r
- case EFI_BROWSER_ACTION_REQUEST_SUBMIT:\r
- SubmitForm (Selection->FormSet, Selection->Form);\r
+ //\r
+ // Check whether Exit flag is TRUE.\r
+ //\r
+ if (gExitRequired) {\r
+ switch (gBrowserSettingScope) {\r
+ case SystemLevel:\r
+ Selection->Action = UI_ACTION_EXIT;\r
break;\r
\r
- case EFI_BROWSER_ACTION_REQUEST_EXIT:\r
- gNvUpdateRequired = FALSE;\r
+ case FormSetLevel:\r
+ case FormLevel:\r
+ FindNextMenu (Selection, gBrowserSettingScope);\r
break;\r
\r
default:\r
break;\r
}\r
+\r
+ gExitRequired = FALSE;\r
}\r
- }\r
\r
+ //\r
+ // Before exit the form, invoke ConfigAccess.Callback() with EFI_BROWSER_ACTION_FORM_CLOSE\r
+ // for each question with callback flag.\r
+ //\r
+ if ((ConfigAccess != NULL) && \r
+ ((Selection->Action == UI_ACTION_EXIT) || \r
+ (Selection->Handle != mCurrentHiiHandle) ||\r
+ (!CompareGuid (&Selection->FormSetGuid, &mCurrentFormSetGuid)) ||\r
+ (Selection->FormId != mCurrentFormId))) {\r
+\r
+ Status = ProcessCallBackFunction (Selection, NULL, EFI_BROWSER_ACTION_FORM_CLOSE, FALSE);\r
+ if (EFI_ERROR (Status)) {\r
+ goto Done;\r
+ }\r
+ }\r
+ } while (Selection->Action == UI_ACTION_REFRESH_FORM);\r
+\r
+Done:\r
//\r
- // Record the old formset\r
+ // Reset current form information to the initial setting when error happens or form exit.\r
//\r
- if (gOldFormSet != NULL) {\r
- DestroyFormSet (gOldFormSet);\r
+ if (EFI_ERROR (Status) || Selection->Action == UI_ACTION_EXIT) {\r
+ mCurrentHiiHandle = NULL;\r
+ CopyGuid (&mCurrentFormSetGuid, &gZeroGuid);\r
+ mCurrentFormId = 0;\r
}\r
- gOldFormSet = FormSet;\r
\r
-Done:\r
//\r
// Unregister notify for Form package update\r
//\r
- Status = mHiiDatabase->UnregisterPackageNotify (\r
- mHiiDatabase,\r
- NotifyHandle\r
- );\r
+ mHiiDatabase->UnregisterPackageNotify (\r
+ mHiiDatabase,\r
+ NotifyHandle\r
+ );\r
return Status;\r
}\r