INF MdeModulePkg/Universal/Console/ConSplitterDxe/ConSplitterDxe.inf\r
INF MdeModulePkg/Universal/HiiDatabaseDxe/HiiDatabaseDxe.inf\r
INF MdeModulePkg/Universal/SetupBrowserDxe/SetupBrowserDxe.inf\r
+INF MdeModulePkg/Universal/DisplayEngineDxe/DisplayEngineDxe.inf\r
\r
INF MdeModulePkg/Universal/Console/GraphicsConsoleDxe/GraphicsConsoleDxe.inf\r
INF MdeModulePkg/Universal/Console/TerminalDxe/TerminalDxe.inf\r
SecurityManagementLib|MdeModulePkg/Library/DxeSecurityManagementLib/DxeSecurityManagementLib.inf\r
CapsuleLib|MdeModulePkg/Library/DxeCapsuleLibNull/DxeCapsuleLibNull.inf\r
PeCoffExtraActionLib|MdePkg/Library/BasePeCoffExtraActionLibNull/BasePeCoffExtraActionLibNull.inf\r
+ CustomizedDisplayLib|MdeModulePkg/Library/CustomizedDisplayLib/CustomizedDisplayLib.inf\r
#\r
# Platform\r
#\r
}\r
MdeModulePkg/Universal/HiiDatabaseDxe/HiiDatabaseDxe.inf\r
MdeModulePkg/Universal/SetupBrowserDxe/SetupBrowserDxe.inf\r
+ MdeModulePkg/Universal/DisplayEngineDxe/DisplayEngineDxe.inf\r
\r
MdeModulePkg/Universal/Console/GraphicsConsoleDxe/GraphicsConsoleDxe.inf\r
MdeModulePkg/Universal/Console/TerminalDxe/TerminalDxe.inf\r
SecurityManagementLib|MdeModulePkg/Library/DxeSecurityManagementLib/DxeSecurityManagementLib.inf\r
CapsuleLib|MdeModulePkg/Library/DxeCapsuleLibNull/DxeCapsuleLibNull.inf\r
PeCoffExtraActionLib|MdePkg/Library/BasePeCoffExtraActionLibNull/BasePeCoffExtraActionLibNull.inf\r
+ CustomizedDisplayLib|MdeModulePkg/Library/CustomizedDisplayLib/CustomizedDisplayLib.inf\r
#\r
# Platform\r
#\r
}\r
MdeModulePkg/Universal/HiiDatabaseDxe/HiiDatabaseDxe.inf\r
MdeModulePkg/Universal/SetupBrowserDxe/SetupBrowserDxe.inf\r
+ MdeModulePkg/Universal/DisplayEngineDxe/DisplayEngineDxe.inf\r
\r
MdeModulePkg/Universal/Console/GraphicsConsoleDxe/GraphicsConsoleDxe.inf\r
MdeModulePkg/Universal/Console/TerminalDxe/TerminalDxe.inf\r
--- /dev/null
+/** @file\r
+ This library class defines a set of interfaces to customize Display module\r
+\r
+Copyright (c) 2013, Intel Corporation. All rights reserved.<BR>\r
+This program and the accompanying materials are licensed and made available under \r
+the terms and conditions of the BSD License that accompanies this distribution. \r
+The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php. \r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, \r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#ifndef __CUSTOMIZED_DISPLAY_LIB_H__\r
+#define __CUSTOMIZED_DISPLAY_LIB_H__\r
+\r
+#include <Protocol/DisplayProtocol.h>\r
+\r
+/**\r
++------------------------------------------------------------------------------+\r
+| Setup Page |\r
++------------------------------------------------------------------------------+\r
+\r
+Statement\r
+Statement\r
+Statement\r
+\r
+\r
+\r
+\r
+\r
++------------------------------------------------------------------------------+\r
+| F9=Reset to Defaults F10=Save |\r
+| ^"=Move Highlight <Spacebar> Toggles Checkbox Esc=Exit |\r
++------------------------------------------------------------------------------+\r
+ StatusBar\r
+**/\r
+\r
+/**\r
+ This funtion defines Page Frame and Backgroud. \r
+ \r
+ Based on the above layout, it will be responsible for HeaderHeight, FooterHeight, \r
+ StatusBarHeight and Backgroud. And, it will reserve Screen for Statement. \r
+\r
+ @param[in] FormData Form Data to be shown in Page.\r
+ @param[out] ScreenForStatement Screen to be used for Statement. (Prompt, Value and Help)\r
+ \r
+ @return Status\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+DisplayPageFrame (\r
+ IN FORM_DISPLAY_ENGINE_FORM *FormData,\r
+ OUT EFI_SCREEN_DESCRIPTOR *ScreenForStatement\r
+ );\r
+\r
+/**\r
+ Clear Screen to the initial state.\r
+**/\r
+VOID\r
+EFIAPI \r
+ClearDisplayPage (\r
+ VOID\r
+ );\r
+\r
+/**\r
+ This function updates customized key panel's help information.\r
+ The library will prepare those Strings for the basic key, ESC, Enter, Up/Down/Left/Right, +/-.\r
+ and arrange them in Footer panel.\r
+ \r
+ @param[in] FormData Form Data to be shown in Page. FormData has the highlighted statement. \r
+ @param[in] Statement The statement current selected.\r
+ @param[in] Selected Whether or not a tag be selected. TRUE means Enter has hit this question.\r
+**/\r
+VOID\r
+EFIAPI\r
+RefreshKeyHelp (\r
+ IN FORM_DISPLAY_ENGINE_FORM *FormData,\r
+ IN FORM_DISPLAY_ENGINE_STATEMENT *Statement,\r
+ IN BOOLEAN Selected\r
+ );\r
+\r
+/**\r
+ Update status bar.\r
+\r
+ This function updates the status bar on the bottom of menu screen. It just shows StatusBar. \r
+ Original logic in this function should be splitted out.\r
+\r
+ @param[in] MessageType The type of message to be shown. InputError or Configuration Changed. \r
+ @param[in] State Show or Clear Message.\r
+**/\r
+VOID\r
+EFIAPI\r
+UpdateStatusBar (\r
+ IN UINTN MessageType,\r
+ IN BOOLEAN State\r
+ );\r
+\r
+/**\r
+ Create popup window. \r
+\r
+ This function draws OEM/Vendor specific pop up windows.\r
+\r
+ @param[out] Key User Input Key\r
+ @param ... String to be shown in Popup. The variable argument list is terminated by a NULL.\r
+ \r
+**/\r
+VOID\r
+EFIAPI\r
+CreateDialog (\r
+ OUT EFI_INPUT_KEY *Key, OPTIONAL\r
+ ...\r
+ );\r
+\r
+/**\r
+ Confirm how to handle the changed data. \r
+ \r
+ @return Action BROWSER_ACTION_SUBMIT, BROWSER_ACTION_DISCARD or other values.\r
+**/\r
+UINTN\r
+EFIAPI\r
+ConfirmDataChange (\r
+ VOID\r
+ );\r
+\r
+/**\r
+ OEM specifies whether Setup exits Page by ESC key.\r
+\r
+ This function customized the behavior that whether Setup exits Page so that \r
+ system able to boot when configuration is not changed.\r
+\r
+ @retval TRUE Exits FrontPage\r
+ @retval FALSE Don't exit FrontPage.\r
+**/\r
+BOOLEAN\r
+EFIAPI\r
+FormExitPolicy (\r
+ VOID\r
+ );\r
+\r
+/**\r
+ Set Timeout value for a ceratain Form to get user response. \r
+ \r
+ This function allows to set timeout value on a ceratain form if necessary.\r
+ If timeout is not zero, the form will exit if user has no response in timeout. \r
+ \r
+ @param[in] FormData Form Data to be shown in Page\r
+\r
+ @return 0 No timeout for this form. \r
+ @return > 0 Timeout value in 100 ns units.\r
+**/\r
+UINT64\r
+EFIAPI\r
+FormExitTimeout (\r
+ IN FORM_DISPLAY_ENGINE_FORM *FormData\r
+ );\r
+\r
+//\r
+// Print Functions\r
+//\r
+/**\r
+ Prints a unicode string to the default console, at\r
+ the supplied cursor position, using L"%s" format.\r
+\r
+ @param Column The cursor position to print the string at. When it is -1, use current Position.\r
+ @param Row The cursor position to print the string at. When it is -1, use current Position.\r
+ @param String String pointer.\r
+\r
+ @return Length of string printed to the console\r
+\r
+**/\r
+UINTN\r
+EFIAPI\r
+PrintStringAt (\r
+ IN UINTN Column,\r
+ IN UINTN Row,\r
+ IN CHAR16 *String\r
+ );\r
+\r
+\r
+/**\r
+ Prints a unicode string with the specified width to the default console, at\r
+ the supplied cursor position, using L"%s" format.\r
+\r
+ @param Column The cursor position to print the string at. When it is -1, use current Position.\r
+ @param Row The cursor position to print the string at. When it is -1, use current Position.\r
+ @param String String pointer.\r
+ @param Width Width for String to be printed. If the print length of String < Width, \r
+ Space char (L' ') will be used to append String. \r
+\r
+ @return Length of string printed to the console\r
+\r
+**/\r
+UINTN\r
+EFIAPI\r
+PrintStringAtWithWidth (\r
+ IN UINTN Column,\r
+ IN UINTN Row,\r
+ IN CHAR16 *String,\r
+ IN UINTN Width\r
+ );\r
+\r
+/**\r
+ Prints a chracter to the default console, at\r
+ the supplied cursor position, using L"%c" format.\r
+\r
+ @param Column The cursor position to print the string at. When it is -1, use current Position.\r
+ @param Row The cursor position to print the string at. When it is -1, use current Position.\r
+ @param Character Character to print.\r
+\r
+ @return Length of string printed to the console.\r
+\r
+**/\r
+UINTN\r
+EFIAPI\r
+PrintCharAt (\r
+ IN UINTN Column,\r
+ IN UINTN Row,\r
+ CHAR16 Character\r
+ );\r
+\r
+/**\r
+ Clear retangle with specified text attribute.\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
+\r
+**/\r
+VOID\r
+EFIAPI\r
+ClearLines (\r
+ IN UINTN LeftColumn,\r
+ IN UINTN RightColumn,\r
+ IN UINTN TopRow,\r
+ IN UINTN BottomRow,\r
+ IN UINTN TextAttribute\r
+ );\r
+\r
+//\r
+// Color Setting Functions\r
+//\r
+/**\r
+ Get OEM/Vendor specific popup attribute colors.\r
+\r
+ @retval Byte code color setting for popup color.\r
+**/\r
+UINT8\r
+EFIAPI\r
+GetPopupColor (\r
+ VOID\r
+ );\r
+\r
+/**\r
+ Get OEM/Vendor specific popup attribute colors.\r
+\r
+ @retval Byte code color setting for popup inverse color.\r
+**/\r
+UINT8\r
+EFIAPI\r
+GetPopupInverseColor (\r
+ VOID\r
+ );\r
+\r
+/**\r
+ Get OEM/Vendor specific PickList color attribute.\r
+\r
+ @retval Byte code color setting for pick list color.\r
+**/\r
+UINT8\r
+EFIAPI\r
+GetPickListColor (\r
+ VOID\r
+ );\r
+\r
+/**\r
+ Get OEM/Vendor specific arrow color attribute.\r
+\r
+ @retval Byte code color setting for arrow color.\r
+**/\r
+UINT8\r
+EFIAPI\r
+GetArrowColor (\r
+ VOID\r
+ );\r
+\r
+/**\r
+ Get OEM/Vendor specific info text color attribute.\r
+\r
+ @retval Byte code color setting for info text color.\r
+**/\r
+UINT8\r
+EFIAPI\r
+GetInfoTextColor (\r
+ VOID\r
+ );\r
+\r
+/**\r
+ Get OEM/Vendor specific help text color attribute.\r
+\r
+ @retval Byte code color setting for help text color.\r
+**/\r
+UINT8\r
+EFIAPI\r
+GetHelpTextColor (\r
+ VOID\r
+ );\r
+\r
+/**\r
+ Get OEM/Vendor specific grayed out text color attribute.\r
+\r
+ @retval Byte code color setting for grayed out text color.\r
+**/\r
+UINT8\r
+EFIAPI\r
+GetGrayedTextColor (\r
+ VOID\r
+ );\r
+\r
+/**\r
+ Get OEM/Vendor specific highlighted text color attribute.\r
+\r
+ @retval Byte code color setting for highlight text color.\r
+**/\r
+UINT8\r
+EFIAPI\r
+GetHighlightTextColor (\r
+ VOID\r
+ );\r
+\r
+/**\r
+ Get OEM/Vendor specific field text color attribute.\r
+\r
+ @retval Byte code color setting for field text color.\r
+**/\r
+UINT8\r
+EFIAPI\r
+GetFieldTextColor (\r
+ VOID\r
+ );\r
+\r
+/**\r
+ Get OEM/Vendor specific subtitle text color attribute.\r
+\r
+ @retval Byte code color setting for subtitle text color.\r
+**/\r
+UINT8\r
+EFIAPI\r
+GetSubTitleTextColor (\r
+ VOID\r
+ );\r
+\r
+#endif\r
--- /dev/null
+/** @file\r
+ FormDiplay protocol to show Form\r
+\r
+Copyright (c) 2013, Intel Corporation. All rights reserved.<BR>\r
+This program and the accompanying materials are licensed and made available under \r
+the terms and conditions of the BSD License that accompanies this distribution. \r
+The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php. \r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, \r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#ifndef __DISPLAY_PROTOCOL_H__\r
+#define __DISPLAY_PROTOCOL_H__\r
+\r
+#include <Protocol\FormBrowser2.h>\r
+\r
+#define EDKII_FORM_DISPLAY_ENGINE_PROTOCOL_GUID \\r
+ { 0x9bbe29e9, 0xfda1, 0x41ec, { 0xad, 0x52, 0x45, 0x22, 0x13, 0x74, 0x2d, 0x2e } }\r
+\r
+// \r
+// Do nothing.\r
+//\r
+#define BROWSER_ACTION_NONE BIT16\r
+//\r
+// ESC Exit\r
+//\r
+#define BROWSER_ACTION_FORM_EXIT BIT17\r
+\r
+#define BROWSER_SUCCESS 0x0\r
+#define BROWSER_ERROR BIT31\r
+#define BROWSER_SUBMIT_FAIL BROWSER_ERROR | 0x01\r
+#define BROWSER_NO_SUBMIT_IF BROWSER_ERROR | 0x02\r
+#define BROWSER_FORM_NOT_FOUND BROWSER_ERROR | 0x03\r
+#define BROWSER_FORM_SUPPRESS BROWSER_ERROR | 0x04\r
+#define BROWSER_PROTOCOL_NOT_FOUND BROWSER_ERROR | 0x05\r
+\r
+#define FORM_DISPLAY_ENGINE_STATEMENT_VERSION_1 0x10000\r
+#define FORM_DISPLAY_ENGINE_VERSION_1 0x10000\r
+\r
+typedef struct {\r
+ //\r
+ // HII Data Type\r
+ //\r
+ UINT8 Type;\r
+ //\r
+ // Buffer Data and Length if Type is EFI_IFR_TYPE_BUFFER or EFI_IFR_TYPE_STRING\r
+ //\r
+ UINT8 *Buffer;\r
+ UINT16 BufferLen;\r
+ EFI_IFR_TYPE_VALUE Value;\r
+} EFI_HII_VALUE;\r
+\r
+#define DISPLAY_QUESTION_OPTION_SIGNATURE SIGNATURE_32 ('Q', 'O', 'P', 'T')\r
+\r
+typedef struct {\r
+ UINTN Signature;\r
+ LIST_ENTRY Link;\r
+ //\r
+ // OneOfOption Data\r
+ //\r
+ EFI_IFR_ONE_OF_OPTION *OptionOpCode;\r
+ //\r
+ // Option ImageId and AnimationId\r
+ //\r
+ EFI_IMAGE_ID ImageId;\r
+ EFI_ANIMATION_ID AnimationId;\r
+} DISPLAY_QUESTION_OPTION;\r
+\r
+#define DISPLAY_QUESTION_OPTION_FROM_LINK(a) CR (a, DISPLAY_QUESTION_OPTION, Link, DISPLAY_QUESTION_OPTION_SIGNATURE)\r
+\r
+typedef struct _FORM_DISPLAY_ENGINE_STATEMENT FORM_DISPLAY_ENGINE_STATEMENT;\r
+typedef struct _FORM_DISPLAY_ENGINE_FORM FORM_DISPLAY_ENGINE_FORM;\r
+\r
+#define STATEMENT_VALID 0x0\r
+#define STATEMENT_INVALID BIT31\r
+\r
+#define INCOSISTENT_IF_TRUE STATEMENT_INVALID | 0x01\r
+#define WARNING_IF_TRUE STATEMENT_INVALID | 0x02\r
+#define STRING_TOO_LONG STATEMENT_INVALID | 0x03\r
+// ... to be extended.\r
+\r
+typedef struct {\r
+ //\r
+ // StringId for INCONSITENT_IF or WARNING_IF\r
+ //\r
+ EFI_STRING_ID StringId;\r
+ //\r
+ // TimeOut for WARNING_IF\r
+ //\r
+ UINT8 TimeOut;\r
+} STATEMENT_ERROR_INFO;\r
+\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 Value New value will be checked.\r
+ \r
+ @retval Status Value Status\r
+\r
+**/\r
+typedef\r
+UINT32\r
+(EFIAPI *VALIDATE_QUESTION) (\r
+ IN FORM_DISPLAY_ENGINE_FORM *Form,\r
+ IN FORM_DISPLAY_ENGINE_STATEMENT *Statement,\r
+ IN EFI_HII_VALUE *Value, \r
+ OUT STATEMENT_ERROR_INFO *ErrorInfo\r
+ );\r
+\r
+/**\r
+ Perform Password check. \r
+ Passwork may be encrypted by driver that requires the specific check.\r
+ \r
+ @param Form Form where Password Statement is in.\r
+ @param Statement Password statement\r
+ @param PasswordString Password string to be checked. It may be NULL.\r
+ NULL means to restore password.\r
+ "" string can be used to checked whether old password does exist.\r
+ \r
+ @return Status Status of Password check.\r
+**/\r
+typedef\r
+EFI_STATUS\r
+(EFIAPI *PASSWORD_CHECK) (\r
+ IN FORM_DISPLAY_ENGINE_FORM *Form,\r
+ IN FORM_DISPLAY_ENGINE_STATEMENT *Statement,\r
+ IN EFI_STRING PasswordString OPTIONAL\r
+ );\r
+\r
+#define FORM_DISPLAY_ENGINE_STATEMENT_SIGNATURE SIGNATURE_32 ('F', 'S', 'T', 'A')\r
+\r
+//\r
+// Attribute for Statement and Form\r
+//\r
+#define HII_DISPLAY_GRAYOUT BIT0\r
+#define HII_DISPLAY_LOCK BIT1\r
+#define HII_DISPLAY_READONLY BIT2\r
+#define HII_DISPLAY_MODAL BIT3\r
+\r
+struct _FORM_DISPLAY_ENGINE_STATEMENT{\r
+ UINTN Signature;\r
+ //\r
+ // Version for future structure extension\r
+ //\r
+ UINTN Version;\r
+ //\r
+ // link to all the statement which will show in the display form.\r
+ //\r
+ LIST_ENTRY DisplayLink;\r
+ //\r
+ // Pointer to statement opcode.\r
+ // for Guided Opcode. All buffers will be here if GUIDED opcode scope is set.\r
+ //\r
+ EFI_IFR_OP_HEADER *OpCode;\r
+ //\r
+ // Question CurrentValue\r
+ //\r
+ EFI_HII_VALUE CurrentValue;\r
+ //\r
+ // Flag to describe whether setting is changed or not.\r
+ // Displayer may depend on it to show it with the different color. \r
+ //\r
+ BOOLEAN SettingChangedFlag;\r
+ //\r
+ // nested Statement list inside of EFI_IFR_SUBTITLE\r
+ //\r
+ LIST_ENTRY NestStatementList;\r
+ //\r
+ // nested EFI_IFR_ONE_OF_OPTION list (QUESTION_OPTION)\r
+ //\r
+ LIST_ENTRY OptionListHead;\r
+ //\r
+ // Statement attributes: GRAYOUT, LOCK and READONLY\r
+ //\r
+ UINT32 Attribute;\r
+\r
+ //\r
+ // ValidateQuestion to do InconsistIf check\r
+ // It may be NULL if any value is valid.\r
+ //\r
+ VALIDATE_QUESTION ValidateQuestion;\r
+ \r
+ //\r
+ // Password additional check. It may be NULL when the additional check is not required.\r
+ //\r
+ PASSWORD_CHECK PasswordCheck;\r
+\r
+ //\r
+ // Statement ImageId and AnimationId\r
+ //\r
+ EFI_IMAGE_ID ImageId;\r
+ EFI_ANIMATION_ID AnimationId;\r
+};\r
+\r
+#define FORM_DISPLAY_ENGINE_STATEMENT_FROM_LINK(a) CR (a, FORM_DISPLAY_ENGINE_STATEMENT, DisplayLink, FORM_DISPLAY_ENGINE_STATEMENT_SIGNATURE)\r
+\r
+#define BROWSER_HOT_KEY_SIGNATURE SIGNATURE_32 ('B', 'H', 'K', 'S')\r
+\r
+typedef struct {\r
+ UINTN Signature;\r
+ LIST_ENTRY Link;\r
+ \r
+ EFI_INPUT_KEY *KeyData;\r
+ //\r
+ // Action is Discard, Default, Submit, Reset and Exit.\r
+ //\r
+ UINT32 Action;\r
+ UINT16 DefaultId;\r
+ //\r
+ // HotKey Help String\r
+ //\r
+ EFI_STRING HelpString;\r
+} BROWSER_HOT_KEY;\r
+\r
+#define BROWSER_HOT_KEY_FROM_LINK(a) CR (a, BROWSER_HOT_KEY, Link, BROWSER_HOT_KEY_SIGNATURE)\r
+\r
+#define FORM_DISPLAY_ENGINE_FORM_SIGNATURE SIGNATURE_32 ('F', 'F', 'R', 'M')\r
+\r
+struct _FORM_DISPLAY_ENGINE_FORM {\r
+ UINTN Signature;\r
+ //\r
+ // Version for future structure extension\r
+ //\r
+ UINTN Version;\r
+ //\r
+ // Statement List inside of Form\r
+ //\r
+ LIST_ENTRY StatementListHead;\r
+ //\r
+ // Statement List outside of Form \r
+ //\r
+ LIST_ENTRY StatementListOSF;\r
+ //\r
+ // The input screen dimenstions info.\r
+ //\r
+ EFI_SCREEN_DESCRIPTOR *ScreenDimensions;\r
+ //\r
+ // FormSet information\r
+ //\r
+ EFI_GUID FormSetGuid;\r
+ //\r
+ // HiiHandle can be used to get String, Image or Animation\r
+ //\r
+ EFI_HII_HANDLE HiiHandle;\r
+ \r
+ //\r
+ // Form ID and Title.\r
+ //\r
+ UINT16 FormId;\r
+ EFI_STRING_ID FormTitle;\r
+ //\r
+ // Form Attributes: Lock, Modal.\r
+ //\r
+ UINT32 Attribute;\r
+ //\r
+ // Flag to describe whether setting is changed or not.\r
+ // Displayer depends on it to show ChangedFlag.\r
+ //\r
+ BOOLEAN SettingChangedFlag;\r
+\r
+ //\r
+ // Statement to be HighLighted\r
+ //\r
+ FORM_DISPLAY_ENGINE_STATEMENT *HighLightedStatement;\r
+ //\r
+ // Event to notify Displayer that FormData is updated to be refreshed.\r
+ //\r
+ EFI_EVENT FormRefreshEvent;\r
+ //\r
+ // Additional Hotkey registered by BrowserEx protocol.\r
+ //\r
+ LIST_ENTRY HotKeyListHead;\r
+\r
+ //\r
+ // Form ImageId and AnimationId\r
+ //\r
+ EFI_IMAGE_ID ImageId;\r
+ EFI_ANIMATION_ID AnimationId;\r
+ \r
+ //\r
+ // If Status is error, display needs to handle it. \r
+ //\r
+ UINT32 BrowserStatus;\r
+ //\r
+ // String for error status. It may be NULL. \r
+ //\r
+ EFI_STRING ErrorString;\r
+};\r
+\r
+#define FORM_DISPLAY_ENGINE_FORM_FROM_LINK(a) CR (a, FORM_DISPLAY_ENGINE_FORM, Link, FORM_DISPLAY_ENGINE_FORM_SIGNATURE)\r
+\r
+typedef struct {\r
+ FORM_DISPLAY_ENGINE_STATEMENT *SelectedStatement; // Selected Statement and InputValue\r
+ \r
+ EFI_HII_VALUE InputValue;\r
+ \r
+ UINT32 Action; // If SelectedStatement is NULL, Action will be used.\r
+ // Trig Action (Discard, Default, Submit, Reset and Exit)\r
+ UINT16 DefaultId;\r
+} USER_INPUT;\r
+\r
+/**\r
+ Display one form, and return user input.\r
+ \r
+ @param FormData Form Data to be shown.\r
+ @param UserInputData User input data.\r
+ \r
+ @retval EFI_SUCCESS Form Data is shown, and user input is got.\r
+**/\r
+typedef\r
+EFI_STATUS\r
+(EFIAPI *FORM_DISPLAY) (\r
+ IN FORM_DISPLAY_ENGINE_FORM *FormData,\r
+ OUT USER_INPUT *UserInputData\r
+);\r
+\r
+/**\r
+ Exit Display and Clear Screen to the original state.\r
+\r
+**/\r
+typedef\r
+VOID\r
+(EFIAPI *EXIT_DISPLAY) (\r
+ VOID\r
+);\r
+\r
+/**\r
+ Confirm how to handle the changed data. \r
+ \r
+ @return Action of Submit, Discard and None\r
+**/\r
+typedef\r
+UINTN\r
+(EFIAPI *CONFIRM_DATA_CHANGE) (\r
+ VOID\r
+);\r
+\r
+typedef struct {\r
+ FORM_DISPLAY FormDisplay;\r
+ EXIT_DISPLAY ExitDisplay;\r
+ CONFIRM_DATA_CHANGE ConfirmDataChange;\r
+} EDKII_FORM_DISPLAY_ENGINE_PROTOCOL;\r
+\r
+extern EFI_GUID gEdkiiFormDisplayEngineProtocolGuid;\r
+#endif\r
--- /dev/null
+/** @file\r
+ Extension Form Browser Protocol provides the services that can be used to \r
+ register the different hot keys for the standard Browser actions described in UEFI specification.\r
+\r
+Copyright (c) 2013, Intel Corporation. All rights reserved.<BR>\r
+This program and the accompanying materials are licensed and made available under \r
+the terms and conditions of the BSD License that accompanies this distribution. \r
+The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php. \r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, \r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#ifndef __FORM_BROWSER_EXTENSION2_H__\r
+#define __FORM_BROWSER_EXTENSION2_H__\r
+\r
+#include <Protocol\FormBrowserEx.h>\r
+\r
+#define EDKII_FORM_BROWSER_EXTENSION2_PROTOCOL_GUID \\r
+ { 0xa770c357, 0xb693, 0x4e6d, { 0xa6, 0xcf, 0xd2, 0x1c, 0x72, 0x8e, 0x55, 0xb }}\r
+\r
+typedef struct _EDKII_FORM_BROWSER_EXTENSION2_PROTOCOL EDKII_FORM_BROWSER_EXTENSION2_PROTOCOL;\r
+\r
+#define BROWSER_EXTENSION2_VERSION_1 0x10000\r
+\r
+/**\r
+ Check whether the browser data has been modified.\r
+\r
+ @retval TRUE Browser data is modified.\r
+ @retval FALSE No browser data is modified.\r
+\r
+**/\r
+typedef\r
+BOOLEAN\r
+(EFIAPI *IS_BROWSER_DATA_MODIFIED) (\r
+ VOID\r
+ );\r
+\r
+/**\r
+ Execute the action requested by the Action parameter.\r
+\r
+ @param[in] Action Execute the request action.\r
+ @param[in] DefaultId The default Id info when need to load default value.\r
+\r
+ @retval EFI_SUCCESS Execute the request action succss.\r
+\r
+**/\r
+typedef \r
+EFI_STATUS \r
+(EFIAPI *EXECUTE_ACTION) (\r
+ IN UINT32 Action,\r
+ IN UINT16 DefaultId\r
+ );\r
+\r
+#define FORM_ENTRY_INFO_SIGNATURE SIGNATURE_32 ('f', 'e', 'i', 's')\r
+\r
+typedef struct {\r
+ UINTN Signature;\r
+ LIST_ENTRY Link;\r
+\r
+ EFI_HII_HANDLE HiiHandle;\r
+ EFI_GUID FormSetGuid;\r
+ EFI_FORM_ID FormId;\r
+ EFI_QUESTION_ID QuestionId;\r
+} FORM_ENTRY_INFO;\r
+\r
+#define FORM_ENTRY_INFO_FROM_LINK(a) CR (a, FORM_ENTRY_INFO, Link, FORM_ENTRY_INFO_SIGNATURE)\r
+\r
+struct _EDKII_FORM_BROWSER_EXTENSION2_PROTOCOL {\r
+ ///\r
+ /// Version for protocol future extension.\r
+ ///\r
+ UINT32 Version;\r
+ SET_SCOPE SetScope;\r
+ REGISTER_HOT_KEY RegisterHotKey;\r
+ REGISTER_EXIT_HANDLER RegiserExitHandler;\r
+ IS_BROWSER_DATA_MODIFIED IsBrowserDataModified;\r
+ EXECUTE_ACTION ExecuteAction;\r
+ ///\r
+ /// A list of type FORMID_INFO is Browser View Form History List.\r
+ ///\r
+ LIST_ENTRY FormViewHistoryHead;\r
+};\r
+\r
+extern EFI_GUID gEdkiiFormBrowserEx2ProtocolGuid;\r
+\r
+#endif\r
+\r
--- /dev/null
+/** @file\r
+MACRO definitions for color used in Setup Browser.\r
+\r
+Copyright (c) 2004 - 2011, 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
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+//\r
+// Unicode collation protocol in\r
+\r
+#ifndef _COLORS_H_\r
+#define _COLORS_H_\r
+\r
+//\r
+// Screen Color Settings\r
+//\r
+#define PICKLIST_HIGHLIGHT_TEXT EFI_WHITE\r
+#define PICKLIST_HIGHLIGHT_BACKGROUND EFI_BACKGROUND_CYAN\r
+#define TITLE_TEXT EFI_WHITE\r
+#define TITLE_BACKGROUND EFI_BACKGROUND_BLUE\r
+#define KEYHELP_TEXT EFI_LIGHTGRAY\r
+#define KEYHELP_BACKGROUND EFI_BACKGROUND_BLACK\r
+#define SUBTITLE_BACKGROUND EFI_BACKGROUND_LIGHTGRAY\r
+#define BANNER_TEXT EFI_BLUE\r
+#define BANNER_BACKGROUND EFI_BACKGROUND_LIGHTGRAY\r
+#define FIELD_TEXT_GRAYED EFI_DARKGRAY\r
+#define FIELD_BACKGROUND EFI_BACKGROUND_LIGHTGRAY\r
+#define POPUP_TEXT EFI_LIGHTGRAY\r
+#define POPUP_BACKGROUND EFI_BACKGROUND_BLUE\r
+#define POPUP_INVERSE_TEXT EFI_LIGHTGRAY\r
+#define POPUP_INVERSE_BACKGROUND EFI_BACKGROUND_BLACK\r
+#define HELP_TEXT EFI_BLUE\r
+#define ERROR_TEXT EFI_RED | EFI_BRIGHT\r
+#define INFO_TEXT EFI_YELLOW | EFI_BRIGHT\r
+#define ARROW_TEXT EFI_RED | EFI_BRIGHT\r
+#define ARROW_BACKGROUND EFI_BACKGROUND_LIGHTGRAY\r
+\r
+#endif\r
--- /dev/null
+/** @file\r
+\r
+ This library class defines a set of interfaces to customize Display module\r
+\r
+Copyright (c) 2013, Intel Corporation. All rights reserved.<BR>\r
+This program and the accompanying materials are licensed and made available under \r
+the terms and conditions of the BSD License that accompanies this distribution. \r
+The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php. \r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, \r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+#include "CustomizedDisplayLibInternal.h"\r
+\r
+EFI_GUID gCustomizedDisplayLibGuid = { 0x99fdc8fd, 0x849b, 0x4eba, { 0xad, 0x13, 0xfb, 0x96, 0x99, 0xc9, 0xa, 0x4d } };\r
+\r
+EFI_HII_HANDLE mCDLStringPackHandle;\r
+UINT16 gClassOfVfr; // Formset class information\r
+BOOLEAN gLibIsFirstForm = TRUE;\r
+BANNER_DATA *gBannerData;\r
+\r
+UINTN gFooterHeight;\r
+\r
+/**\r
++------------------------------------------------------------------------------+\r
+| Setup Page |\r
++------------------------------------------------------------------------------+\r
+\r
+Statement\r
+Statement\r
+Statement\r
+\r
+\r
+\r
+\r
+\r
++------------------------------------------------------------------------------+\r
+| F9=Reset to Defaults F10=Save |\r
+| ^"=Move Highlight <Spacebar> Toggles Checkbox Esc=Exit |\r
++------------------------------------------------------------------------------+\r
+ StatusBar\r
+**/\r
+\r
+/**\r
+ This funtion defines Page Frame and Backgroud. \r
+ \r
+ Based on the above layout, it will be responsible for HeaderHeight, FooterHeight, \r
+ StatusBarHeight and Backgroud. And, it will reserve Screen for Statement. \r
+\r
+ @param[in] FormData Form Data to be shown in Page.\r
+ @param[out] ScreenForStatement Screen to be used for Statement. (Prompt, Value and Help)\r
+ \r
+ @return Status\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+DisplayPageFrame (\r
+ IN FORM_DISPLAY_ENGINE_FORM *FormData,\r
+ OUT EFI_SCREEN_DESCRIPTOR *ScreenForStatement\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+\r
+ ASSERT (FormData != NULL && ScreenForStatement != NULL);\r
+ if (FormData == NULL || ScreenForStatement == NULL) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ Status = ScreenDiemensionInfoValidate (FormData);\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ gClassOfVfr = FORMSET_CLASS_PLATFORM_SETUP;\r
+\r
+ ProcessExternedOpcode(FormData);\r
+\r
+ //\r
+ // Calculate the ScreenForStatement.\r
+ //\r
+ ScreenForStatement->BottomRow = gScreenDimensions.BottomRow - STATUS_BAR_HEIGHT - gFooterHeight;\r
+ if (gClassOfVfr == FORMSET_CLASS_FRONT_PAGE) {\r
+ ScreenForStatement->TopRow = gScreenDimensions.TopRow + FRONT_PAGE_HEADER_HEIGHT;\r
+ } else {\r
+ ScreenForStatement->TopRow = gScreenDimensions.TopRow + NONE_FRONT_PAGE_HEADER_HEIGHT;\r
+ }\r
+ ScreenForStatement->LeftColumn = gScreenDimensions.LeftColumn;\r
+ ScreenForStatement->RightColumn = gScreenDimensions.RightColumn;\r
+\r
+ if ((gLibIsFirstForm) || ((FormData->Attribute & HII_DISPLAY_MODAL) != 0)) {\r
+ //\r
+ // Ensure we are in Text mode\r
+ //\r
+ gST->ConOut->SetAttribute (gST->ConOut, EFI_TEXT_ATTR (EFI_LIGHTGRAY, EFI_BLACK));\r
+ ClearLines (0, gScreenDimensions.RightColumn, 0, gScreenDimensions.BottomRow, KEYHELP_BACKGROUND);\r
+ gLibIsFirstForm = FALSE;\r
+ }\r
+\r
+ //\r
+ // Don't print frame for modal form.\r
+ //\r
+ if ((FormData->Attribute & HII_DISPLAY_MODAL) != 0) {\r
+ return EFI_SUCCESS;\r
+ }\r
+\r
+ if (gClassOfVfr == FORMSET_CLASS_FRONT_PAGE) {\r
+ PrintBannerInfo (FormData);\r
+ }\r
+\r
+ PrintFramework (FormData);\r
+\r
+ UpdateStatusBar(NV_UPDATE_REQUIRED, FormData->SettingChangedFlag);\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+ This function updates customized key panel's help information.\r
+ The library will prepare those Strings for the basic key, ESC, Enter, Up/Down/Left/Right, +/-.\r
+ and arrange them in Footer panel.\r
+ \r
+ @param[in] FormData Form Data to be shown in Page. FormData has the highlighted statement. \r
+ @param[in] Statement The statement current selected.\r
+ @param[in] Selected Whether or not a tag be selected. TRUE means Enter has hit this question.\r
+**/\r
+VOID\r
+EFIAPI\r
+RefreshKeyHelp (\r
+ IN FORM_DISPLAY_ENGINE_FORM *FormData,\r
+ IN FORM_DISPLAY_ENGINE_STATEMENT *Statement,\r
+ IN BOOLEAN Selected\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_IFR_NUMERIC *NumericOp;\r
+ EFI_IFR_DATE *DateOp;\r
+ EFI_IFR_TIME *TimeOp;\r
+ BOOLEAN HexDisplay;\r
+\r
+ ASSERT (FormData != NULL);\r
+ if (FormData == NULL) {\r
+ return;\r
+ }\r
+\r
+ gST->ConOut->SetAttribute (gST->ConOut, KEYHELP_TEXT | KEYHELP_BACKGROUND);\r
+\r
+ if ((FormData->Attribute & HII_DISPLAY_MODAL) != 0) {\r
+ return;\r
+ }\r
+\r
+ SecCol = gScreenDimensions.LeftColumn + (gScreenDimensions.RightColumn - gScreenDimensions.LeftColumn) / 3;\r
+ ThdCol = gScreenDimensions.LeftColumn + (gScreenDimensions.RightColumn - gScreenDimensions.LeftColumn) / 3 * 2;\r
+\r
+ StartColumnOfHelp = gScreenDimensions.LeftColumn + 2;\r
+ LeftColumnOfHelp = gScreenDimensions.LeftColumn + 1;\r
+ RightColumnOfHelp = gScreenDimensions.RightColumn - 2;\r
+ TopRowOfHelp = gScreenDimensions.BottomRow - STATUS_BAR_HEIGHT - gFooterHeight + 1;\r
+ BottomRowOfHelp = gScreenDimensions.BottomRow - STATUS_BAR_HEIGHT - 2;\r
+\r
+ ClearLines (LeftColumnOfHelp, RightColumnOfHelp, TopRowOfHelp, BottomRowOfHelp, KEYHELP_TEXT | KEYHELP_BACKGROUND);\r
+ if (Statement == NULL) {\r
+ //\r
+ // Print Key for Form without showable statement.\r
+ //\r
+ PrintHotKeyHelpString (FormData);\r
+ PrintStringAt (ThdCol, BottomRowOfHelp, gEscapeString);\r
+ return;\r
+ }\r
+\r
+ HexDisplay = FALSE;\r
+ NumericOp = NULL;\r
+ DateOp = NULL;\r
+ TimeOp = NULL;\r
+ if (Statement->OpCode->OpCode == EFI_IFR_NUMERIC_OP) {\r
+ NumericOp = (EFI_IFR_NUMERIC *) Statement->OpCode;\r
+ HexDisplay = (NumericOp->Flags & EFI_IFR_DISPLAY_UINT_HEX) == EFI_IFR_DISPLAY_UINT_HEX;\r
+ } else if (Statement->OpCode->OpCode == EFI_IFR_DATE_OP) {\r
+ DateOp = (EFI_IFR_DATE *) Statement->OpCode;\r
+ HexDisplay = (DateOp->Flags & EFI_IFR_DISPLAY_UINT_HEX) == EFI_IFR_DISPLAY_UINT_HEX;\r
+ } else if (Statement->OpCode->OpCode == EFI_IFR_TIME_OP) {\r
+ TimeOp = (EFI_IFR_TIME *) Statement->OpCode;\r
+ HexDisplay = (TimeOp->Flags & EFI_IFR_DISPLAY_UINT_HEX) == EFI_IFR_DISPLAY_UINT_HEX;\r
+ } \r
+ switch (Statement->OpCode->OpCode) {\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
+ if (!Selected) {\r
+ PrintHotKeyHelpString (FormData);\r
+\r
+ if (gClassOfVfr == FORMSET_CLASS_PLATFORM_SETUP) {\r
+ PrintStringAt (ThdCol, BottomRowOfHelp, gEscapeString);\r
+ }\r
+\r
+ if ((Statement->OpCode->OpCode == EFI_IFR_DATE_OP) ||\r
+ (Statement->OpCode->OpCode == EFI_IFR_TIME_OP)) {\r
+ PrintAt (\r
+ 0, \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, gEnterString);\r
+ PrintStringAt (StartColumnOfHelp, TopRowOfHelp, gAdjustNumber);\r
+ } else {\r
+ PrintAt (0, StartColumnOfHelp, BottomRowOfHelp, L"%c%c%s", ARROW_UP, ARROW_DOWN, gMoveHighlight);\r
+ if (Statement->OpCode->OpCode == EFI_IFR_NUMERIC_OP && NumericOp != NULL && LibGetFieldFromNum(Statement->OpCode) != 0) {\r
+ PrintStringAt (StartColumnOfHelp, TopRowOfHelp, gAdjustNumber);\r
+ } \r
+ PrintStringAt (SecCol, BottomRowOfHelp, gEnterString);\r
+ }\r
+ } else {\r
+ PrintStringAt (SecCol, BottomRowOfHelp, gEnterCommitString);\r
+\r
+ //\r
+ // If it is a selected numeric with manual input, display different message\r
+ //\r
+ if ((Statement->OpCode->OpCode == EFI_IFR_NUMERIC_OP) || \r
+ (Statement->OpCode->OpCode == EFI_IFR_DATE_OP) ||\r
+ (Statement->OpCode->OpCode == EFI_IFR_TIME_OP)) {\r
+ PrintStringAt (\r
+ SecCol,\r
+ TopRowOfHelp,\r
+ HexDisplay ? gHexNumericInput : gDecNumericInput\r
+ );\r
+ } else if (Statement->OpCode->OpCode != EFI_IFR_ORDERED_LIST_OP) {\r
+ PrintAt (0, StartColumnOfHelp, BottomRowOfHelp, L"%c%c%s", ARROW_UP, ARROW_DOWN, gMoveHighlight);\r
+ }\r
+\r
+ if (Statement->OpCode->OpCode == EFI_IFR_ORDERED_LIST_OP) {\r
+ PrintStringAt (StartColumnOfHelp, TopRowOfHelp, gPlusString);\r
+ PrintStringAt (ThdCol, TopRowOfHelp, gMinusString);\r
+ }\r
+\r
+ PrintStringAt (ThdCol, BottomRowOfHelp, gEnterEscapeString);\r
+ }\r
+ break;\r
+\r
+ case EFI_IFR_CHECKBOX_OP:\r
+ PrintHotKeyHelpString (FormData);\r
+\r
+ if (gClassOfVfr == FORMSET_CLASS_PLATFORM_SETUP) {\r
+ PrintStringAt (ThdCol, BottomRowOfHelp, gEscapeString);\r
+ }\r
+\r
+ PrintAt (0, StartColumnOfHelp, BottomRowOfHelp, L"%c%c%s", ARROW_UP, ARROW_DOWN, gMoveHighlight);\r
+ PrintStringAt (SecCol, BottomRowOfHelp, gToggleCheckBox);\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
+ case EFI_IFR_SUBTITLE_OP:\r
+ if (!Selected) {\r
+ PrintHotKeyHelpString (FormData);\r
+\r
+ if (gClassOfVfr == FORMSET_CLASS_PLATFORM_SETUP) {\r
+ PrintStringAt (ThdCol, BottomRowOfHelp, gEscapeString);\r
+ }\r
+\r
+ PrintAt (0, StartColumnOfHelp, BottomRowOfHelp, L"%c%c%s", ARROW_UP, ARROW_DOWN, gMoveHighlight);\r
+ if (Statement->OpCode->OpCode != EFI_IFR_TEXT_OP && Statement->OpCode->OpCode != EFI_IFR_SUBTITLE_OP) {\r
+ PrintStringAt (SecCol, BottomRowOfHelp, gEnterString);\r
+ }\r
+ } else {\r
+ if (Statement->OpCode->OpCode != EFI_IFR_REF_OP) {\r
+ PrintStringAt (\r
+ (gScreenDimensions.RightColumn - LibGetStringWidth (gEnterCommitString) / 2) / 2,\r
+ BottomRowOfHelp,\r
+ gEnterCommitString\r
+ );\r
+ PrintStringAt (ThdCol, BottomRowOfHelp, gEnterEscapeString);\r
+ }\r
+ }\r
+ break;\r
+\r
+ default:\r
+ break;\r
+ } \r
+}\r
+\r
+/**\r
+ Update status bar.\r
+\r
+ This function updates the status bar on the bottom of menu screen. It just shows StatusBar. \r
+ Original logic in this function should be splitted out.\r
+\r
+ @param[in] MessageType The type of message to be shown. InputError or Configuration Changed. \r
+ @param[in] State Show or Clear Message.\r
+**/\r
+VOID\r
+EFIAPI\r
+UpdateStatusBar (\r
+ IN UINTN MessageType,\r
+ IN BOOLEAN State\r
+ )\r
+{\r
+ UINTN Index;\r
+ CHAR16 OptionWidth;\r
+\r
+ OptionWidth = (CHAR16) ((gScreenDimensions.RightColumn - gScreenDimensions.LeftColumn) / 3);\r
+\r
+ switch (MessageType) {\r
+ case INPUT_ERROR:\r
+ if (State) {\r
+ gST->ConOut->SetAttribute (gST->ConOut, ERROR_TEXT);\r
+ PrintStringAt (\r
+ gScreenDimensions.LeftColumn + OptionWidth,\r
+ gScreenDimensions.BottomRow - 1,\r
+ gInputErrorMessage\r
+ );\r
+ } else {\r
+ gST->ConOut->SetAttribute (gST->ConOut, KEYHELP_BACKGROUND);\r
+ for (Index = 0; Index < (LibGetStringWidth (gInputErrorMessage) - 2) / 2; Index++) {\r
+ PrintStringAt (gScreenDimensions.LeftColumn + OptionWidth + Index, gScreenDimensions.BottomRow - 1, L" ");\r
+ }\r
+ }\r
+ break;\r
+\r
+ case NV_UPDATE_REQUIRED:\r
+ //\r
+ // Global setting support. Show configuration change on every form.\r
+ //\r
+ if (State) {\r
+ gST->ConOut->SetAttribute (gST->ConOut, INFO_TEXT);\r
+ PrintStringAt (\r
+ gScreenDimensions.LeftColumn + OptionWidth * 2,\r
+ gScreenDimensions.BottomRow - 1,\r
+ gNvUpdateMessage\r
+ );\r
+ } else {\r
+ gST->ConOut->SetAttribute (gST->ConOut, KEYHELP_BACKGROUND);\r
+ for (Index = 0; Index < (LibGetStringWidth (gNvUpdateMessage) - 2) / 2; Index++) {\r
+ PrintStringAt (\r
+ (gScreenDimensions.LeftColumn + OptionWidth * 2 + Index),\r
+ gScreenDimensions.BottomRow - 1,\r
+ L" "\r
+ );\r
+ }\r
+ }\r
+ break;\r
+\r
+ default:\r
+ break;\r
+ } \r
+}\r
+\r
+/**\r
+ Create popup window. It will replace CreateDialog(). \r
+\r
+ This function draws OEM/Vendor specific pop up windows.\r
+\r
+ @param[out] Key User Input Key\r
+ @param ... String to be shown in Popup. The variable argument list is terminated by a NULL.\r
+ \r
+**/\r
+VOID\r
+EFIAPI\r
+CreateDialog (\r
+ OUT EFI_INPUT_KEY *Key, OPTIONAL\r
+ ...\r
+ )\r
+{\r
+ VA_LIST Marker;\r
+ EFI_INPUT_KEY KeyValue;\r
+ EFI_STATUS Status;\r
+ UINTN LargestString;\r
+ UINTN LineNum;\r
+ UINTN Index;\r
+ UINTN Count;\r
+ CHAR16 Character;\r
+ UINTN Start;\r
+ UINTN End;\r
+ UINTN Top;\r
+ UINTN Bottom;\r
+ CHAR16 *String;\r
+ UINTN DimensionsWidth;\r
+ UINTN DimensionsHeight;\r
+ UINTN CurrentAttribute;\r
+\r
+ //\r
+ // If screen dimension info is not ready, get it from console.\r
+ //\r
+ if (gScreenDimensions.RightColumn == 0 || gScreenDimensions.BottomRow == 0) {\r
+ ZeroMem (&gScreenDimensions, sizeof (EFI_SCREEN_DESCRIPTOR));\r
+ gST->ConOut->QueryMode (\r
+ gST->ConOut,\r
+ gST->ConOut->Mode->Mode,\r
+ &gScreenDimensions.RightColumn,\r
+ &gScreenDimensions.BottomRow\r
+ );\r
+ }\r
+\r
+ DimensionsWidth = gScreenDimensions.RightColumn - gScreenDimensions.LeftColumn;\r
+ DimensionsHeight = gScreenDimensions.BottomRow - gScreenDimensions.TopRow;\r
+\r
+ LargestString = 0;\r
+ LineNum = 0;\r
+ VA_START (Marker, Key);\r
+ while ((String = VA_ARG (Marker, CHAR16 *)) != NULL) {\r
+ LineNum ++;\r
+ \r
+ if ((LibGetStringWidth (String) / 2) > LargestString) {\r
+ LargestString = (LibGetStringWidth (String) / 2);\r
+ }\r
+ } \r
+ VA_END (Marker);\r
+\r
+ if ((LargestString + 2) > DimensionsWidth) {\r
+ LargestString = DimensionsWidth - 2;\r
+ }\r
+ \r
+ CurrentAttribute = gST->ConOut->Mode->Attribute; \r
+ gST->ConOut->EnableCursor (gST->ConOut, FALSE);\r
+ gST->ConOut->SetAttribute (gST->ConOut, GetPopupColor ());\r
+\r
+ //\r
+ // Subtract the PopUp width from total Columns, allow for one space extra on\r
+ // each end plus a border.\r
+ //\r
+ Start = (DimensionsWidth - LargestString - 2) / 2 + gScreenDimensions.LeftColumn + 1;\r
+ End = Start + LargestString + 1;\r
+\r
+ Top = ((DimensionsHeight - LineNum - 2) / 2) + gScreenDimensions.TopRow - 1;\r
+ Bottom = Top + LineNum + 2;\r
+\r
+ Character = BOXDRAW_DOWN_RIGHT;\r
+ PrintCharAt (Start, Top, Character);\r
+ Character = BOXDRAW_HORIZONTAL;\r
+ for (Index = Start; Index + 2 < End; Index++) {\r
+ PrintCharAt ((UINTN)-1, (UINTN)-1, Character);\r
+ }\r
+\r
+ Character = BOXDRAW_DOWN_LEFT;\r
+ PrintCharAt ((UINTN)-1, (UINTN)-1, Character);\r
+ Character = BOXDRAW_VERTICAL;\r
+\r
+ Count = 0;\r
+ VA_START (Marker, Key);\r
+ for (Index = Top; Index + 2 < Bottom; Index++, Count++) {\r
+ String = VA_ARG (Marker, CHAR16*);\r
+\r
+ if (String[0] == CHAR_NULL) {\r
+ //\r
+ // Passing in a NULL results in a blank space\r
+ //\r
+ ClearLines (Start, End, Index + 1, Index + 1, GetPopupColor ());\r
+ } else if (String[0] == L' ') {\r
+ //\r
+ // Passing in a space results in the assumption that this is where typing will occur\r
+ //\r
+ ClearLines (Start + 1, End - 1, Index + 1, Index + 1, POPUP_INVERSE_TEXT | POPUP_INVERSE_BACKGROUND);\r
+ PrintStringAt (\r
+ ((DimensionsWidth - LibGetStringWidth (String) / 2) / 2) + gScreenDimensions.LeftColumn + 1,\r
+ Index + 1,\r
+ String + 1\r
+ );\r
+ } else {\r
+ //\r
+ // This will clear the background of the line - we never know who might have been\r
+ // here before us. This differs from the next clear in that it used the non-reverse\r
+ // video for normal printing.\r
+ //\r
+ ClearLines (Start, End, Index + 1, Index + 1, GetPopupColor ());\r
+ PrintStringAt (\r
+ ((DimensionsWidth - LibGetStringWidth (String) / 2) / 2) + gScreenDimensions.LeftColumn + 1,\r
+ Index + 1,\r
+ String\r
+ );\r
+ }\r
+\r
+ gST->ConOut->SetAttribute (gST->ConOut, GetPopupColor ());\r
+ PrintCharAt (Start, Index + 1, Character);\r
+ PrintCharAt (End - 1, Index + 1, Character);\r
+ }\r
+ VA_END (Marker);\r
+\r
+ Character = BOXDRAW_UP_RIGHT;\r
+ PrintCharAt (Start, Bottom - 1, Character);\r
+ Character = BOXDRAW_HORIZONTAL;\r
+ for (Index = Start; Index + 2 < End; Index++) {\r
+ PrintCharAt ((UINTN)-1, (UINTN) -1, Character);\r
+ }\r
+\r
+ Character = BOXDRAW_UP_LEFT;\r
+ PrintCharAt ((UINTN)-1, (UINTN) -1, Character);\r
+\r
+ if (Key != NULL) {\r
+ Status = WaitForKeyStroke (&KeyValue);\r
+ ASSERT_EFI_ERROR (Status);\r
+ CopyMem (Key, &KeyValue, sizeof (EFI_INPUT_KEY));\r
+ }\r
+\r
+ gST->ConOut->SetAttribute (gST->ConOut, CurrentAttribute);\r
+ gST->ConOut->EnableCursor (gST->ConOut, TRUE);\r
+}\r
+\r
+/**\r
+ Confirm how to handle the changed data. \r
+ \r
+ @return Action BROWSER_ACTION_SUBMIT, BROWSER_ACTION_DISCARD or other values.\r
+**/\r
+UINTN\r
+EFIAPI\r
+ConfirmDataChange (\r
+ VOID\r
+ )\r
+{\r
+ CHAR16 YesResponse;\r
+ CHAR16 NoResponse;\r
+ EFI_INPUT_KEY Key;\r
+\r
+ gST->ConIn->ReadKeyStroke (gST->ConIn, &Key);\r
+ \r
+ YesResponse = gYesResponse[0];\r
+ NoResponse = gNoResponse[0];\r
+ \r
+ //\r
+ // If NV flag is up, prompt user\r
+ //\r
+ do {\r
+ CreateDialog (&Key, gLibEmptyString, gSaveChanges, gAreYouSure, gLibEmptyString, NULL);\r
+ } while\r
+ (\r
+ (Key.ScanCode != SCAN_ESC) &&\r
+ ((Key.UnicodeChar | UPPER_LOWER_CASE_OFFSET) != (NoResponse | UPPER_LOWER_CASE_OFFSET)) &&\r
+ ((Key.UnicodeChar | UPPER_LOWER_CASE_OFFSET) != (YesResponse | UPPER_LOWER_CASE_OFFSET))\r
+ );\r
+ \r
+ if (Key.ScanCode == SCAN_ESC) {\r
+ return BROWSER_ACTION_NONE;\r
+ } else if ((Key.UnicodeChar | UPPER_LOWER_CASE_OFFSET) == (YesResponse | UPPER_LOWER_CASE_OFFSET)) {\r
+ return BROWSER_ACTION_SUBMIT;\r
+ } else {\r
+ return BROWSER_ACTION_DISCARD;\r
+ }\r
+}\r
+\r
+/**\r
+ OEM specifies whether Setup exits Page by ESC key.\r
+\r
+ This function customized the behavior that whether Setup exits Page so that \r
+ system able to boot when configuration is not changed.\r
+\r
+ @retval TRUE Exits FrontPage\r
+ @retval FALSE Don't exit FrontPage.\r
+**/\r
+BOOLEAN\r
+EFIAPI\r
+FormExitPolicy (\r
+ VOID\r
+ )\r
+{\r
+ return gClassOfVfr == FORMSET_CLASS_FRONT_PAGE ? FALSE : TRUE;\r
+}\r
+\r
+/**\r
+ Set Timeout value for a ceratain Form to get user response. \r
+ \r
+ This function allows to set timeout value on a ceratain form if necessary.\r
+ If timeout is not zero, the form will exit if user has no response in timeout. \r
+ \r
+ @param[in] FormData Form Data to be shown in Page\r
+\r
+ @return 0 No timeout for this form. \r
+ @return > 0 Timeout value in 100 ns units.\r
+**/\r
+UINT64\r
+EFIAPI\r
+FormExitTimeout (\r
+ IN FORM_DISPLAY_ENGINE_FORM *FormData\r
+ )\r
+{\r
+ return 0;\r
+}\r
+//\r
+// Print Functions\r
+//\r
+/**\r
+ Prints a unicode string to the default console, at\r
+ the supplied cursor position, using L"%s" format.\r
+\r
+ @param Column The cursor position to print the string at. When it is -1, use current Position.\r
+ @param Row The cursor position to print the string at. When it is -1, use current Position.\r
+ @param String String pointer.\r
+\r
+ @return Length of string printed to the console\r
+\r
+**/\r
+UINTN\r
+EFIAPI\r
+PrintStringAt (\r
+ IN UINTN Column,\r
+ IN UINTN Row,\r
+ IN CHAR16 *String\r
+ )\r
+{\r
+ return PrintAt (0, Column, Row, L"%s", String);\r
+}\r
+\r
+/**\r
+ Prints a unicode string to the default console, at\r
+ the supplied cursor position, using L"%s" format.\r
+\r
+ @param Column The cursor position to print the string at. When it is -1, use current Position.\r
+ @param Row The cursor position to print the string at. When it is -1, use current Position.\r
+ @param String String pointer.\r
+ @param Width Width for String.\r
+\r
+ @return Length of string printed to the console\r
+\r
+**/\r
+UINTN\r
+EFIAPI\r
+PrintStringAtWithWidth (\r
+ IN UINTN Column,\r
+ IN UINTN Row,\r
+ IN CHAR16 *String,\r
+ IN UINTN Width\r
+ )\r
+{\r
+ return PrintAt (Width, Column, Row, L"%s", String);\r
+}\r
+\r
+/**\r
+ Prints a chracter to the default console, at\r
+ the supplied cursor position, using L"%c" format.\r
+\r
+ @param Column The cursor position to print the string at. When it is -1, use current Position.\r
+ @param Row The cursor position to print the string at. When it is -1, use current Position.\r
+ @param Character Character to print.\r
+\r
+ @return Length of string printed to the console.\r
+\r
+**/\r
+UINTN\r
+EFIAPI\r
+PrintCharAt (\r
+ IN UINTN Column,\r
+ IN UINTN Row,\r
+ CHAR16 Character\r
+ )\r
+{\r
+ return PrintAt (0, Column, Row, L"%c", Character);\r
+}\r
+\r
+/**\r
+ Clear retangle with specified text attribute.\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
+\r
+**/\r
+VOID\r
+EFIAPI\r
+ClearLines (\r
+ IN UINTN LeftColumn,\r
+ IN UINTN RightColumn,\r
+ IN UINTN TopRow,\r
+ IN UINTN BottomRow,\r
+ IN UINTN TextAttribute\r
+ )\r
+{\r
+ CHAR16 *Buffer;\r
+ UINTN Row;\r
+\r
+ //\r
+ // For now, allocate an arbitrarily long buffer\r
+ //\r
+ Buffer = AllocateZeroPool (0x10000);\r
+ ASSERT (Buffer != NULL);\r
+\r
+ //\r
+ // Set foreground and background as defined\r
+ //\r
+ gST->ConOut->SetAttribute (gST->ConOut, TextAttribute);\r
+\r
+ //\r
+ // Much faster to buffer the long string instead of print it a character at a time\r
+ //\r
+ LibSetUnicodeMem (Buffer, RightColumn - LeftColumn, L' ');\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
+ }\r
+\r
+ gST->ConOut->SetCursorPosition (gST->ConOut, LeftColumn, TopRow);\r
+\r
+ FreePool (Buffer);\r
+}\r
+\r
+//\r
+// Color Setting Functions\r
+//\r
+\r
+/**\r
+ Get OEM/Vendor specific popup attribute colors.\r
+\r
+ @retval Byte code color setting for popup color.\r
+**/\r
+UINT8\r
+EFIAPI\r
+GetPopupColor (\r
+ VOID\r
+ )\r
+{\r
+ return POPUP_TEXT | POPUP_BACKGROUND;\r
+}\r
+\r
+/**\r
+ Get OEM/Vendor specific popup attribute colors.\r
+\r
+ @retval Byte code color setting for popup inverse color.\r
+**/\r
+UINT8\r
+EFIAPI\r
+GetPopupInverseColor (\r
+ VOID\r
+ )\r
+{\r
+ return POPUP_INVERSE_TEXT | POPUP_INVERSE_BACKGROUND;\r
+}\r
+\r
+/**\r
+ Get OEM/Vendor specific PickList color attribute.\r
+\r
+ @retval Byte code color setting for pick list color.\r
+**/\r
+UINT8\r
+EFIAPI\r
+GetPickListColor (\r
+ VOID\r
+ )\r
+{\r
+ return PICKLIST_HIGHLIGHT_TEXT | PICKLIST_HIGHLIGHT_BACKGROUND;\r
+}\r
+\r
+/**\r
+ Get OEM/Vendor specific arrow color attribute.\r
+\r
+ @retval Byte code color setting for arrow color.\r
+**/\r
+UINT8\r
+EFIAPI\r
+GetArrowColor (\r
+ VOID\r
+ )\r
+{\r
+ return ARROW_TEXT | ARROW_BACKGROUND;\r
+}\r
+\r
+/**\r
+ Get OEM/Vendor specific info text color attribute.\r
+\r
+ @retval Byte code color setting for info text color.\r
+**/\r
+UINT8\r
+EFIAPI\r
+GetInfoTextColor (\r
+ VOID\r
+ )\r
+{\r
+ return INFO_TEXT | FIELD_BACKGROUND;\r
+}\r
+\r
+/**\r
+ Get OEM/Vendor specific help text color attribute.\r
+\r
+ @retval Byte code color setting for help text color.\r
+**/\r
+UINT8\r
+EFIAPI\r
+GetHelpTextColor (\r
+ VOID\r
+ )\r
+{\r
+ return HELP_TEXT | FIELD_BACKGROUND;\r
+}\r
+\r
+/**\r
+ Get OEM/Vendor specific grayed out text color attribute.\r
+\r
+ @retval Byte code color setting for grayed out text color.\r
+**/\r
+UINT8\r
+EFIAPI\r
+GetGrayedTextColor (\r
+ VOID\r
+ )\r
+{\r
+ return FIELD_TEXT_GRAYED | FIELD_BACKGROUND;\r
+}\r
+\r
+/**\r
+ Get OEM/Vendor specific highlighted text color attribute.\r
+\r
+ @retval Byte code color setting for highlight text color.\r
+**/\r
+UINT8\r
+EFIAPI\r
+GetHighlightTextColor (\r
+ VOID\r
+ )\r
+{\r
+ return PcdGet8 (PcdBrowserFieldTextHighlightColor) | PcdGet8 (PcdBrowserFieldBackgroundHighlightColor);\r
+}\r
+\r
+/**\r
+ Get OEM/Vendor specific field text color attribute.\r
+\r
+ @retval Byte code color setting for field text color.\r
+**/\r
+UINT8\r
+EFIAPI\r
+GetFieldTextColor (\r
+ VOID\r
+ )\r
+{\r
+ return PcdGet8 (PcdBrowserFieldTextColor) | FIELD_BACKGROUND;\r
+}\r
+\r
+/**\r
+ Get OEM/Vendor specific subtitle text color attribute.\r
+\r
+ @retval Byte code color setting for subtitle text color.\r
+**/\r
+UINT8\r
+EFIAPI\r
+GetSubTitleTextColor (\r
+ VOID\r
+ )\r
+{\r
+ return PcdGet8 (PcdBrowserSubtitleTextColor) | FIELD_BACKGROUND;\r
+}\r
+\r
+/**\r
+ Clear Screen to the initial state.\r
+**/\r
+VOID\r
+EFIAPI \r
+ClearDisplayPage (\r
+ VOID\r
+ )\r
+{\r
+ gST->ConOut->SetAttribute (gST->ConOut, EFI_TEXT_ATTR (EFI_LIGHTGRAY, EFI_BLACK));\r
+ gST->ConOut->ClearScreen (gST->ConOut);\r
+ gLibIsFirstForm = TRUE;\r
+}\r
+\r
+/**\r
+ Constructor of Customized Display Library Instance.\r
+\r
+ @param ImageHandle The firmware allocated handle for the EFI image.\r
+ @param SystemTable A pointer to the EFI System Table.\r
+\r
+ @retval EFI_SUCCESS The constructor always returns EFI_SUCCESS.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+CustomizedDisplayLibConstructor (\r
+ IN EFI_HANDLE ImageHandle,\r
+ IN EFI_SYSTEM_TABLE *SystemTable\r
+ )\r
+{\r
+ mCDLStringPackHandle = HiiAddPackages (&gCustomizedDisplayLibGuid, ImageHandle, CustomizedDisplayLibStrings, NULL);\r
+ ASSERT (mCDLStringPackHandle != NULL);\r
+\r
+ InitializeLibStrings();\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+ Destructor of Customized Display Library Instance.\r
+\r
+ @param ImageHandle The firmware allocated handle for the EFI image.\r
+ @param SystemTable A pointer to the EFI System Table.\r
+\r
+ @retval EFI_SUCCESS The destructor completed successfully.\r
+ @retval Other value The destructor did not complete successfully.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+CustomizedDisplayLibDestructor (\r
+ IN EFI_HANDLE ImageHandle,\r
+ IN EFI_SYSTEM_TABLE *SystemTable\r
+ )\r
+{\r
+ HiiRemovePackages(mCDLStringPackHandle);\r
+ \r
+ FreeLibStrings ();\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
--- /dev/null
+##\r
+# This file contains an 'Intel Peripheral Driver' and is \r
+# licensed for Intel CPUs and chipsets under the terms of your \r
+# license agreement with Intel or your vendor. This file may \r
+# be modified by the user, subject to additional terms of the \r
+# license agreement \r
+##\r
+## @file\r
+# \r
+# General BDS defines and produce general interfaces for platform BDS driver including:\r
+# 1) BDS boot policy interface;\r
+# 2) BDS boot device connect interface;\r
+# 3) BDS Misc interfaces for mainting boot variable, ouput string, etc.\r
+# \r
+# Copyright (c) 2007 - 2010, Intel Corporation. All rights reserved.<BR>\r
+# This software and associated documentation (if any) is furnished\r
+# under a license and may only be used or copied in accordance\r
+# with the terms of the license. Except as permitted by such\r
+# license, no part of this software or documentation may be\r
+# reproduced, stored in a retrieval system, or transmitted in any\r
+# form or by any means without the express written consent of\r
+# Intel Corporation.\r
+# \r
+##\r
+\r
+[Defines]\r
+ INF_VERSION = 0x00010005\r
+ BASE_NAME = CustomizedDisplayLib\r
+ FILE_GUID = 80B92017-EC64-4923-938D-94FAEE85832E\r
+ MODULE_TYPE = DXE_DRIVER\r
+ VERSION_STRING = 1.0\r
+ LIBRARY_CLASS = CustomizedDisplayLib|DXE_DRIVER UEFI_APPLICATION\r
+ CONSTRUCTOR = CustomizedDisplayLibConstructor\r
+ DESTRUCTOR = CustomizedDisplayLibDestructor\r
+#\r
+# The following information is for reference only and not required by the build tools.\r
+#\r
+# VALID_ARCHITECTURES = IA32 X64 IPF EBC\r
+#\r
+\r
+[Sources]\r
+ CustomizedDisplayLib.c\r
+ Colors.h\r
+ CustomizedDisplayLibInternal.h\r
+ CustomizedDisplayLibInternal.c\r
+ CustomizedDisplayLib.uni\r
+ \r
+[Packages]\r
+ MdePkg/MdePkg.dec\r
+ MdeModulePkg/MdeModulePkg.dec\r
+\r
+[LibraryClasses]\r
+ MemoryAllocationLib\r
+ BaseLib\r
+ UefiBootServicesTableLib\r
+ UefiDriverEntryPoint\r
+ UefiRuntimeServicesTableLib\r
+ BaseMemoryLib\r
+ DebugLib\r
+ PrintLib\r
+ HiiLib\r
+ DevicePathLib\r
+ PcdLib\r
+\r
+[Guids]\r
+ gEfiIfrTianoGuid\r
+ \r
+[Protocols]\r
+\r
+[Pcd]\r
+ gEfiMdeModulePkgTokenSpaceGuid.PcdBrowserSubtitleTextColor ## CONSUMES\r
+ gEfiMdeModulePkgTokenSpaceGuid.PcdBrowserFieldTextColor ## CONSUMES\r
+ gEfiMdeModulePkgTokenSpaceGuid.PcdBrowserFieldTextHighlightColor ## CONSUMES\r
+ gEfiMdeModulePkgTokenSpaceGuid.PcdBrowserFieldBackgroundHighlightColor ## CONSUMES
\ No newline at end of file
--- /dev/null
+/** @file\r
+\r
+ This library class defines a set of interfaces to customize Display module\r
+\r
+Copyright (c) 2013, Intel Corporation. All rights reserved.<BR>\r
+This program and the accompanying materials are licensed and made available under \r
+the terms and conditions of the BSD License that accompanies this distribution. \r
+The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php. \r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, \r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+#include "CustomizedDisplayLibInternal.h"\r
+\r
+EFI_SCREEN_DESCRIPTOR gScreenDimensions;\r
+CHAR16 *mLibUnknownString;\r
+extern EFI_HII_HANDLE mCDLStringPackHandle;\r
+CHAR16 *mSpaceBuffer;\r
+#define SPACE_BUFFER_SIZE 1000\r
+\r
+//\r
+// Browser Global Strings\r
+//\r
+CHAR16 *gEnterString;\r
+CHAR16 *gEnterCommitString;\r
+CHAR16 *gEnterEscapeString;\r
+CHAR16 *gEscapeString;\r
+CHAR16 *gMoveHighlight;\r
+CHAR16 *gDecNumericInput;\r
+CHAR16 *gHexNumericInput;\r
+CHAR16 *gToggleCheckBox;\r
+CHAR16 *gLibEmptyString;\r
+CHAR16 *gAreYouSure;\r
+CHAR16 *gYesResponse;\r
+CHAR16 *gNoResponse;\r
+CHAR16 *gPlusString;\r
+CHAR16 *gMinusString;\r
+CHAR16 *gAdjustNumber;\r
+CHAR16 *gSaveChanges;\r
+CHAR16 *gNvUpdateMessage;\r
+CHAR16 *gInputErrorMessage;\r
+\r
+/**\r
+\r
+ Print banner info for front page.\r
+\r
+ @param[in] FormData Form Data to be shown in Page\r
+ \r
+**/\r
+VOID\r
+PrintBannerInfo ( \r
+ IN FORM_DISPLAY_ENGINE_FORM *FormData\r
+ )\r
+{\r
+ UINT8 Line;\r
+ UINT8 Alignment;\r
+ CHAR16 *StrFrontPageBanner;\r
+ UINT8 RowIdx;\r
+ UINT8 ColumnIdx;\r
+\r
+ //\r
+ // ClearLines(0, LocalScreen.RightColumn, 0, BANNER_HEIGHT-1, BANNER_TEXT | BANNER_BACKGROUND);\r
+ //\r
+ ClearLines (\r
+ gScreenDimensions.LeftColumn,\r
+ gScreenDimensions.RightColumn,\r
+ gScreenDimensions.TopRow,\r
+ FRONT_PAGE_HEADER_HEIGHT - 1 + gScreenDimensions.TopRow,\r
+ BANNER_TEXT | BANNER_BACKGROUND\r
+ );\r
+\r
+ //\r
+ // for (Line = 0; Line < BANNER_HEIGHT; Line++) {\r
+ //\r
+ for (Line = (UINT8) gScreenDimensions.TopRow; Line < BANNER_HEIGHT + (UINT8) gScreenDimensions.TopRow; Line++) {\r
+ //\r
+ // for (Alignment = 0; Alignment < BANNER_COLUMNS; Alignment++) {\r
+ //\r
+ for (Alignment = (UINT8) gScreenDimensions.LeftColumn;\r
+ Alignment < BANNER_COLUMNS + (UINT8) gScreenDimensions.LeftColumn;\r
+ Alignment++\r
+ ) {\r
+ RowIdx = (UINT8) (Line - (UINT8) gScreenDimensions.TopRow);\r
+ ColumnIdx = (UINT8) (Alignment - (UINT8) gScreenDimensions.LeftColumn);\r
+ \r
+ ASSERT (RowIdx < BANNER_HEIGHT && ColumnIdx < BANNER_COLUMNS);\r
+ \r
+ if (gBannerData!= NULL && gBannerData->Banner[RowIdx][ColumnIdx] != 0x0000) {\r
+ StrFrontPageBanner = LibGetToken (gBannerData->Banner[RowIdx][ColumnIdx], FormData->HiiHandle);\r
+ } else {\r
+ continue;\r
+ }\r
+ \r
+ switch (Alignment - gScreenDimensions.LeftColumn) {\r
+ case 0:\r
+ //\r
+ // Handle left column\r
+ //\r
+ PrintStringAt (gScreenDimensions.LeftColumn + BANNER_LEFT_COLUMN_INDENT, Line, StrFrontPageBanner);\r
+ break;\r
+ \r
+ case 1:\r
+ //\r
+ // Handle center column\r
+ //\r
+ PrintStringAt (\r
+ gScreenDimensions.LeftColumn + (gScreenDimensions.RightColumn - gScreenDimensions.LeftColumn) / 3,\r
+ Line,\r
+ StrFrontPageBanner\r
+ );\r
+ break;\r
+ \r
+ case 2:\r
+ //\r
+ // Handle right column\r
+ //\r
+ PrintStringAt (\r
+ gScreenDimensions.LeftColumn + (gScreenDimensions.RightColumn - gScreenDimensions.LeftColumn) * 2 / 3,\r
+ Line,\r
+ StrFrontPageBanner\r
+ );\r
+ break;\r
+ }\r
+ \r
+ FreePool (StrFrontPageBanner);\r
+ }\r
+ }\r
+}\r
+\r
+/**\r
+ Print framework and form title for a page.\r
+\r
+ @param[in] FormData Form Data to be shown in Page\r
+**/\r
+VOID\r
+PrintFramework (\r
+ IN FORM_DISPLAY_ENGINE_FORM *FormData\r
+ )\r
+{\r
+ UINTN Index;\r
+ CHAR16 Character;\r
+ CHAR16 *Buffer;\r
+ UINTN Row;\r
+ CHAR16 *TitleStr;\r
+\r
+ if (gClassOfVfr != FORMSET_CLASS_PLATFORM_SETUP) {\r
+ //\r
+ // Only Setup page needs Framework\r
+ //\r
+ ClearLines (\r
+ gScreenDimensions.LeftColumn,\r
+ gScreenDimensions.RightColumn,\r
+ gScreenDimensions.BottomRow - STATUS_BAR_HEIGHT - gFooterHeight,\r
+ gScreenDimensions.BottomRow - STATUS_BAR_HEIGHT - 1,\r
+ KEYHELP_TEXT | KEYHELP_BACKGROUND\r
+ );\r
+ return;\r
+ }\r
+ \r
+ Buffer = AllocateZeroPool (0x10000);\r
+ ASSERT (Buffer != NULL);\r
+ Character = BOXDRAW_HORIZONTAL;\r
+ for (Index = 0; Index + 2 < (gScreenDimensions.RightColumn - gScreenDimensions.LeftColumn); Index++) {\r
+ Buffer[Index] = Character;\r
+ }\r
+\r
+ //\r
+ // Print Top border line\r
+ // +------------------------------------------------------------------------------+\r
+ // ? ?\r
+ // +------------------------------------------------------------------------------+\r
+ //\r
+ gST->ConOut->SetAttribute (gST->ConOut, TITLE_TEXT | TITLE_BACKGROUND);\r
+ Character = BOXDRAW_DOWN_RIGHT;\r
+\r
+ PrintCharAt (gScreenDimensions.LeftColumn, gScreenDimensions.TopRow, Character);\r
+ PrintStringAt ((UINTN) -1, (UINTN) -1, Buffer);\r
+\r
+ Character = BOXDRAW_DOWN_LEFT;\r
+ PrintCharAt ((UINTN) -1, (UINTN) -1, Character);\r
+\r
+ Character = BOXDRAW_VERTICAL;\r
+ for (Row = gScreenDimensions.TopRow + 1; Row <= gScreenDimensions.TopRow + NONE_FRONT_PAGE_HEADER_HEIGHT - 2; Row++) {\r
+ PrintCharAt (gScreenDimensions.LeftColumn, Row, Character);\r
+ PrintCharAt (gScreenDimensions.RightColumn - 1, Row, Character);\r
+ }\r
+ \r
+ //\r
+ // Print Form Title\r
+ //\r
+ ClearLines (\r
+ gScreenDimensions.LeftColumn + 1,\r
+ gScreenDimensions.RightColumn - 1,\r
+ gScreenDimensions.TopRow + 1,\r
+ gScreenDimensions.TopRow + 1,\r
+ TITLE_TEXT | TITLE_BACKGROUND\r
+ );\r
+\r
+ TitleStr = LibGetToken (FormData->FormTitle, FormData->HiiHandle);\r
+ ASSERT (TitleStr != NULL);\r
+ PrintStringAt (\r
+ (gScreenDimensions.RightColumn + gScreenDimensions.LeftColumn - LibGetStringWidth (TitleStr) / 2) / 2,\r
+ gScreenDimensions.TopRow + 1,\r
+ TitleStr\r
+ );\r
+ FreePool (TitleStr);\r
+\r
+ Character = BOXDRAW_UP_RIGHT;\r
+ PrintCharAt (gScreenDimensions.LeftColumn, gScreenDimensions.TopRow + NONE_FRONT_PAGE_HEADER_HEIGHT - 1, Character);\r
+ PrintStringAt ((UINTN) -1, (UINTN) -1, Buffer);\r
+\r
+ Character = BOXDRAW_UP_LEFT;\r
+ PrintCharAt ((UINTN) -1, (UINTN) -1, Character);\r
+\r
+ //\r
+ // Print Bottom border line\r
+ // +------------------------------------------------------------------------------+\r
+ // ? ?\r
+ // +------------------------------------------------------------------------------+\r
+ //\r
+ Character = BOXDRAW_DOWN_RIGHT;\r
+ PrintCharAt (gScreenDimensions.LeftColumn, gScreenDimensions.BottomRow - STATUS_BAR_HEIGHT - gFooterHeight, Character);\r
+\r
+ PrintStringAt ((UINTN) -1, (UINTN) -1, Buffer);\r
+\r
+ Character = BOXDRAW_DOWN_LEFT;\r
+ PrintCharAt ((UINTN) -1, (UINTN) -1, Character);\r
+ Character = BOXDRAW_VERTICAL;\r
+ for (Row = gScreenDimensions.BottomRow - STATUS_BAR_HEIGHT - gFooterHeight + 1;\r
+ Row <= gScreenDimensions.BottomRow - STATUS_BAR_HEIGHT - 2;\r
+ Row++\r
+ ) {\r
+ PrintCharAt (gScreenDimensions.LeftColumn, Row, Character);\r
+ PrintCharAt (gScreenDimensions.RightColumn - 1, Row, Character);\r
+ }\r
+\r
+ Character = BOXDRAW_UP_RIGHT;\r
+ PrintCharAt (gScreenDimensions.LeftColumn, gScreenDimensions.BottomRow - STATUS_BAR_HEIGHT - 1, Character);\r
+\r
+ PrintStringAt ((UINTN) -1, (UINTN) -1, Buffer);\r
+\r
+ Character = BOXDRAW_UP_LEFT;\r
+ PrintCharAt ((UINTN) -1, (UINTN) -1, Character);\r
+ \r
+ FreePool (Buffer);\r
+}\r
+\r
+/**\r
+ Process some op code which is not recognized by browser core.\r
+\r
+ @param OpCodeData The pointer to the op code buffer.\r
+\r
+ @return EFI_SUCCESS Pass the statement success.\r
+\r
+**/\r
+VOID\r
+ProcessUserOpcode(\r
+ IN EFI_IFR_OP_HEADER *OpCodeData\r
+ )\r
+{\r
+ switch (OpCodeData->OpCode) {\r
+ case EFI_IFR_GUID_OP: \r
+ if (CompareGuid (&gEfiIfrTianoGuid, (EFI_GUID *)((CHAR8*) OpCodeData + sizeof (EFI_IFR_OP_HEADER)))) {\r
+ //\r
+ // Tiano specific GUIDed opcodes\r
+ //\r
+ switch (((EFI_IFR_GUID_LABEL *) OpCodeData)->ExtendOpCode) {\r
+ case EFI_IFR_EXTEND_OP_LABEL:\r
+ //\r
+ // just ignore label\r
+ //\r
+ break;\r
+\r
+ case EFI_IFR_EXTEND_OP_BANNER:\r
+ //\r
+ // Only in front page form set, we care about the banner data.\r
+ //\r
+ if (gClassOfVfr == FORMSET_CLASS_FRONT_PAGE) {\r
+ //\r
+ // Initialize Driver private data\r
+ //\r
+ if (gBannerData == NULL) {\r
+ gBannerData = AllocateZeroPool (sizeof (BANNER_DATA));\r
+ ASSERT (gBannerData != NULL);\r
+ }\r
+ \r
+ CopyMem (\r
+ &gBannerData->Banner[((EFI_IFR_GUID_BANNER *) OpCodeData)->LineNumber][\r
+ ((EFI_IFR_GUID_BANNER *) OpCodeData)->Alignment],\r
+ &((EFI_IFR_GUID_BANNER *) OpCodeData)->Title,\r
+ sizeof (EFI_STRING_ID)\r
+ );\r
+ }\r
+ break;\r
+\r
+ case EFI_IFR_EXTEND_OP_SUBCLASS:\r
+ if (((EFI_IFR_GUID_SUBCLASS *) OpCodeData)->SubClass == EFI_FRONT_PAGE_SUBCLASS) {\r
+ gClassOfVfr = FORMSET_CLASS_FRONT_PAGE;\r
+ }\r
+ break;\r
+\r
+ default:\r
+ break;\r
+ }\r
+ }\r
+ break;\r
+\r
+ default:\r
+ break;\r
+ }\r
+}\r
+\r
+/**\r
+ Process some op codes which is out side of current form.\r
+ \r
+ @param FormData Pointer to the form data.\r
+\r
+ @return EFI_SUCCESS Pass the statement success.\r
+\r
+**/\r
+VOID\r
+ProcessExternedOpcode (\r
+ IN FORM_DISPLAY_ENGINE_FORM *FormData\r
+ )\r
+{\r
+ LIST_ENTRY *Link;\r
+ FORM_DISPLAY_ENGINE_STATEMENT *Statement;\r
+\r
+ Link = GetFirstNode (&FormData->StatementListOSF);\r
+ while (!IsNull (&FormData->StatementListOSF, Link)) {\r
+ Statement = FORM_DISPLAY_ENGINE_STATEMENT_FROM_LINK (Link);\r
+ Link = GetNextNode (&FormData->StatementListOSF, Link);\r
+\r
+ ProcessUserOpcode(Statement->OpCode);\r
+ }\r
+\r
+ Link = GetFirstNode (&FormData->StatementListHead);\r
+ while (!IsNull (&FormData->StatementListHead, Link)) {\r
+ Statement = FORM_DISPLAY_ENGINE_STATEMENT_FROM_LINK (Link);\r
+ Link = GetNextNode (&FormData->StatementListHead, Link);\r
+\r
+ ProcessUserOpcode(Statement->OpCode);\r
+ }\r
+}\r
+\r
+/**\r
+ Validate the input screen diemenstion info.\r
+\r
+ @param FormData The input form data info.\r
+\r
+ @return EFI_SUCCESS The input screen info is acceptable.\r
+ @return EFI_INVALID_PARAMETER The input screen info is not acceptable.\r
+\r
+**/\r
+EFI_STATUS \r
+ScreenDiemensionInfoValidate (\r
+ IN FORM_DISPLAY_ENGINE_FORM *FormData\r
+ )\r
+{\r
+ LIST_ENTRY *Link;\r
+ UINTN Index;\r
+\r
+ //\r
+ // Calculate total number of Register HotKeys. \r
+ //\r
+ Index = 0;\r
+ if (!IsListEmpty (&FormData->HotKeyListHead)){\r
+ Link = GetFirstNode (&FormData->HotKeyListHead);\r
+ while (!IsNull (&FormData->HotKeyListHead, Link)) {\r
+ Link = GetNextNode (&FormData->HotKeyListHead, Link);\r
+ Index ++;\r
+ }\r
+ }\r
+\r
+ //\r
+ // Show three HotKeys help information on one row.\r
+ //\r
+ gFooterHeight = FOOTER_HEIGHT + (Index / 3);\r
+\r
+\r
+ ZeroMem (&gScreenDimensions, sizeof (EFI_SCREEN_DESCRIPTOR));\r
+ gST->ConOut->QueryMode (\r
+ gST->ConOut,\r
+ gST->ConOut->Mode->Mode,\r
+ &gScreenDimensions.RightColumn,\r
+ &gScreenDimensions.BottomRow\r
+ );\r
+\r
+ //\r
+ // Check local dimension vs. global dimension.\r
+ //\r
+ if (FormData->ScreenDimensions != NULL) {\r
+ if ((gScreenDimensions.RightColumn < FormData->ScreenDimensions->RightColumn) ||\r
+ (gScreenDimensions.BottomRow < FormData->ScreenDimensions->BottomRow)\r
+ ) {\r
+ return EFI_INVALID_PARAMETER;\r
+ } else {\r
+ //\r
+ // Local dimension validation.\r
+ //\r
+ if ((FormData->ScreenDimensions->RightColumn > FormData->ScreenDimensions->LeftColumn) &&\r
+ (FormData->ScreenDimensions->BottomRow > FormData->ScreenDimensions->TopRow) &&\r
+ ((FormData->ScreenDimensions->RightColumn - FormData->ScreenDimensions->LeftColumn) > 2) &&\r
+ ((FormData->ScreenDimensions->BottomRow - FormData->ScreenDimensions->TopRow) > STATUS_BAR_HEIGHT +\r
+ FRONT_PAGE_HEADER_HEIGHT + gFooterHeight + 3)) {\r
+ CopyMem (&gScreenDimensions, (VOID *) FormData->ScreenDimensions, sizeof (EFI_SCREEN_DESCRIPTOR));\r
+ } else {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+ }\r
+ }\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+ Get the string based on the StringId and HII Package List Handle.\r
+\r
+ @param Token The String's ID.\r
+ @param HiiHandle The package list in the HII database to search for\r
+ the specified string.\r
+\r
+ @return The output string.\r
+\r
+**/\r
+CHAR16 *\r
+LibGetToken (\r
+ IN EFI_STRING_ID Token,\r
+ IN EFI_HII_HANDLE HiiHandle\r
+ )\r
+{\r
+ EFI_STRING String;\r
+\r
+ String = HiiGetString (HiiHandle, Token, NULL);\r
+ if (String == NULL) {\r
+ String = AllocateCopyPool (StrSize (mLibUnknownString), mLibUnknownString);\r
+ ASSERT (String != NULL);\r
+ }\r
+\r
+ return (CHAR16 *) String;\r
+}\r
+\r
+\r
+/**\r
+ Count the storage space of a Unicode string.\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
+\r
+ If String is NULL, then ASSERT ().\r
+\r
+ @param String The input string to be counted.\r
+\r
+ @return Storage space for the input string.\r
+\r
+**/\r
+UINTN\r
+LibGetStringWidth (\r
+ IN CHAR16 *String\r
+ )\r
+{\r
+ UINTN Index;\r
+ UINTN Count;\r
+ UINTN IncrementValue;\r
+\r
+ ASSERT (String != NULL);\r
+ if (String == NULL) {\r
+ return 0;\r
+ }\r
+\r
+ Index = 0;\r
+ Count = 0;\r
+ IncrementValue = 1;\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
+\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
+ //\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
+ }\r
+ } while (String[Index] != 0);\r
+\r
+ //\r
+ // Increment by one to include the null-terminator in the size\r
+ //\r
+ Count++;\r
+\r
+ return Count * sizeof (CHAR16);\r
+}\r
+\r
+/**\r
+ Show all registered HotKey help strings on bottom Rows.\r
+\r
+ @param FormData The curent input form data info.\r
+\r
+**/\r
+VOID\r
+PrintHotKeyHelpString (\r
+ IN FORM_DISPLAY_ENGINE_FORM *FormData\r
+ )\r
+{\r
+ UINTN CurrentCol;\r
+ UINTN CurrentRow;\r
+ UINTN BottomRowOfHotKeyHelp;\r
+ UINTN ColumnWidth;\r
+ UINTN Index;\r
+ EFI_SCREEN_DESCRIPTOR LocalScreen;\r
+ LIST_ENTRY *Link;\r
+ BROWSER_HOT_KEY *HotKey;\r
+\r
+ if (IsListEmpty (&FormData->HotKeyListHead)) {\r
+ return;\r
+ }\r
+\r
+ CopyMem (&LocalScreen, &gScreenDimensions, sizeof (EFI_SCREEN_DESCRIPTOR));\r
+ ColumnWidth = (LocalScreen.RightColumn - LocalScreen.LeftColumn) / 3;\r
+ BottomRowOfHotKeyHelp = LocalScreen.BottomRow - STATUS_BAR_HEIGHT - 3;\r
+\r
+ //\r
+ // Calculate total number of Register HotKeys. \r
+ //\r
+ Index = 0;\r
+ Link = GetFirstNode (&FormData->HotKeyListHead);\r
+ while (!IsNull (&FormData->HotKeyListHead, Link)) {\r
+ HotKey = BROWSER_HOT_KEY_FROM_LINK (Link);\r
+ //\r
+ // Help string can't exceed ColumnWidth. One Row will show three Help information. \r
+ //\r
+ if (StrLen (HotKey->HelpString) > ColumnWidth) {\r
+ HotKey->HelpString[ColumnWidth] = L'\0';\r
+ }\r
+ //\r
+ // Calculate help information Column and Row.\r
+ //\r
+ if ((Index % 3) != 2) {\r
+ CurrentCol = LocalScreen.LeftColumn + (2 - Index % 3) * ColumnWidth;\r
+ } else {\r
+ CurrentCol = LocalScreen.LeftColumn + 2;\r
+ }\r
+ CurrentRow = BottomRowOfHotKeyHelp - Index / 3;\r
+ //\r
+ // Print HotKey help string on bottom Row.\r
+ //\r
+ PrintStringAt (CurrentCol, CurrentRow, HotKey->HelpString);\r
+\r
+ //\r
+ // Get Next Hot Key.\r
+ //\r
+ Link = GetNextNode (&FormData->HotKeyListHead, Link);\r
+ Index ++;\r
+ }\r
+ \r
+ return;\r
+}\r
+\r
+/**\r
+ Get step info from numeric opcode.\r
+ \r
+ @param[in] OpCode The input numeric op code.\r
+\r
+ @return step info for this opcode.\r
+**/\r
+UINT64\r
+LibGetFieldFromNum (\r
+ IN EFI_IFR_OP_HEADER *OpCode\r
+ )\r
+{\r
+ EFI_IFR_NUMERIC *NumericOp;\r
+ UINT64 Step;\r
+\r
+ NumericOp = (EFI_IFR_NUMERIC *) OpCode;\r
+ \r
+ switch (NumericOp->Flags & EFI_IFR_NUMERIC_SIZE) {\r
+ case EFI_IFR_NUMERIC_SIZE_1:\r
+ Step = NumericOp->data.u8.Step;\r
+ break;\r
+ \r
+ case EFI_IFR_NUMERIC_SIZE_2:\r
+ Step = NumericOp->data.u16.Step;\r
+ break;\r
+ \r
+ case EFI_IFR_NUMERIC_SIZE_4:\r
+ Step = NumericOp->data.u32.Step;\r
+ break;\r
+ \r
+ case EFI_IFR_NUMERIC_SIZE_8:\r
+ Step = NumericOp->data.u64.Step;\r
+ break;\r
+ \r
+ default:\r
+ Step = 0;\r
+ break;\r
+ }\r
+\r
+ return Step;\r
+}\r
+\r
+/**\r
+ Initialize the HII String Token to the correct values.\r
+\r
+**/\r
+VOID\r
+InitializeLibStrings (\r
+ VOID\r
+ )\r
+{\r
+ mLibUnknownString = L"!";\r
+\r
+ gEnterString = LibGetToken (STRING_TOKEN (ENTER_STRING), mCDLStringPackHandle);\r
+ gEnterCommitString = LibGetToken (STRING_TOKEN (ENTER_COMMIT_STRING), mCDLStringPackHandle);\r
+ gEnterEscapeString = LibGetToken (STRING_TOKEN (ENTER_ESCAPE_STRING), mCDLStringPackHandle);\r
+ gEscapeString = LibGetToken (STRING_TOKEN (ESCAPE_STRING), mCDLStringPackHandle);\r
+ gMoveHighlight = LibGetToken (STRING_TOKEN (MOVE_HIGHLIGHT), mCDLStringPackHandle);\r
+ gDecNumericInput = LibGetToken (STRING_TOKEN (DEC_NUMERIC_INPUT), mCDLStringPackHandle);\r
+ gHexNumericInput = LibGetToken (STRING_TOKEN (HEX_NUMERIC_INPUT), mCDLStringPackHandle);\r
+ gToggleCheckBox = LibGetToken (STRING_TOKEN (TOGGLE_CHECK_BOX), mCDLStringPackHandle);\r
+\r
+ gAreYouSure = LibGetToken (STRING_TOKEN (ARE_YOU_SURE), mCDLStringPackHandle);\r
+ gYesResponse = LibGetToken (STRING_TOKEN (ARE_YOU_SURE_YES), mCDLStringPackHandle);\r
+ gNoResponse = LibGetToken (STRING_TOKEN (ARE_YOU_SURE_NO), mCDLStringPackHandle);\r
+ gPlusString = LibGetToken (STRING_TOKEN (PLUS_STRING), mCDLStringPackHandle);\r
+ gMinusString = LibGetToken (STRING_TOKEN (MINUS_STRING), mCDLStringPackHandle);\r
+ gAdjustNumber = LibGetToken (STRING_TOKEN (ADJUST_NUMBER), mCDLStringPackHandle);\r
+ gSaveChanges = LibGetToken (STRING_TOKEN (SAVE_CHANGES), mCDLStringPackHandle);\r
+\r
+ gLibEmptyString = LibGetToken (STRING_TOKEN (EMPTY_STRING), mCDLStringPackHandle);\r
+\r
+ gNvUpdateMessage = LibGetToken (STRING_TOKEN (NV_UPDATE_MESSAGE), mCDLStringPackHandle);\r
+ gInputErrorMessage = LibGetToken (STRING_TOKEN (INPUT_ERROR_MESSAGE), mCDLStringPackHandle);\r
+ \r
+ //\r
+ // SpaceBuffer;\r
+ //\r
+ mSpaceBuffer = AllocatePool ((SPACE_BUFFER_SIZE + 1) * sizeof (CHAR16));\r
+ ASSERT (mSpaceBuffer != NULL);\r
+ LibSetUnicodeMem (mSpaceBuffer, SPACE_BUFFER_SIZE, L' ');\r
+ mSpaceBuffer[SPACE_BUFFER_SIZE] = L'\0';\r
+}\r
+\r
+\r
+/**\r
+ Free the HII String.\r
+\r
+**/\r
+VOID\r
+FreeLibStrings (\r
+ VOID\r
+ )\r
+{\r
+ FreePool (gEnterString);\r
+ FreePool (gEnterCommitString);\r
+ FreePool (gEnterEscapeString);\r
+ FreePool (gEscapeString);\r
+ FreePool (gMoveHighlight);\r
+ FreePool (gDecNumericInput);\r
+ FreePool (gHexNumericInput);\r
+ FreePool (gToggleCheckBox);\r
+\r
+ FreePool (gAreYouSure);\r
+ FreePool (gYesResponse);\r
+ FreePool (gNoResponse);\r
+ FreePool (gPlusString);\r
+ FreePool (gMinusString);\r
+ FreePool (gAdjustNumber);\r
+ FreePool (gSaveChanges);\r
+\r
+ FreePool (gLibEmptyString);\r
+\r
+ FreePool (gNvUpdateMessage);\r
+ FreePool (gInputErrorMessage);\r
+ \r
+ FreePool (mSpaceBuffer);\r
+}\r
+\r
+/**\r
+ Wait for a key to be pressed by user.\r
+\r
+ @param Key The key which is pressed by user.\r
+\r
+ @retval EFI_SUCCESS The function always completed successfully.\r
+\r
+**/\r
+EFI_STATUS\r
+WaitForKeyStroke (\r
+ OUT EFI_INPUT_KEY *Key\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ UINTN Index;\r
+\r
+ while (TRUE) {\r
+ Status = gST->ConIn->ReadKeyStroke (gST->ConIn, Key);\r
+ if (!EFI_ERROR (Status)) {\r
+ break;\r
+ }\r
+\r
+ if (Status != EFI_NOT_READY) {\r
+ continue;\r
+ }\r
+ \r
+ gBS->WaitForEvent (1, &gST->ConIn->WaitForKey, &Index);\r
+ }\r
+ return Status;\r
+}\r
+\r
+\r
+/**\r
+ Set Buffer to Value for Size bytes.\r
+\r
+ @param Buffer Memory to set.\r
+ @param Size Number of bytes to set\r
+ @param Value Value of the set operation.\r
+\r
+**/\r
+VOID\r
+LibSetUnicodeMem (\r
+ IN VOID *Buffer,\r
+ IN UINTN Size,\r
+ IN CHAR16 Value\r
+ )\r
+{\r
+ CHAR16 *Ptr;\r
+\r
+ Ptr = Buffer;\r
+ while ((Size--) != 0) {\r
+ *(Ptr++) = Value;\r
+ }\r
+}\r
+\r
+/**\r
+ The internal function prints to the EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL\r
+ protocol instance.\r
+\r
+ @param Width Width of string to be print.\r
+ @param Column The position of the output string.\r
+ @param Row The position of the output string.\r
+ @param Out The EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL instance.\r
+ @param Fmt The format string.\r
+ @param Args The additional argument for the variables in the format string.\r
+\r
+ @return Number of Unicode character printed.\r
+\r
+**/\r
+UINTN\r
+PrintInternal (\r
+ IN UINTN Width, \r
+ IN UINTN Column,\r
+ IN UINTN Row,\r
+ IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *Out,\r
+ IN CHAR16 *Fmt,\r
+ IN VA_LIST Args\r
+ )\r
+{\r
+ CHAR16 *Buffer;\r
+ CHAR16 *BackupBuffer;\r
+ UINTN Index;\r
+ UINTN PreviousIndex;\r
+ UINTN Count;\r
+ UINTN PrintWidth;\r
+ UINTN CharWidth;\r
+\r
+ //\r
+ // For now, allocate an arbitrarily long buffer\r
+ //\r
+ Buffer = AllocateZeroPool (0x10000);\r
+ BackupBuffer = AllocateZeroPool (0x10000);\r
+ ASSERT (Buffer);\r
+ ASSERT (BackupBuffer);\r
+\r
+ if (Column != (UINTN) -1) {\r
+ Out->SetCursorPosition (Out, Column, Row);\r
+ }\r
+\r
+ UnicodeVSPrint (Buffer, 0x10000, Fmt, Args);\r
+\r
+ Out->Mode->Attribute = Out->Mode->Attribute & 0x7f;\r
+\r
+ Out->SetAttribute (Out, Out->Mode->Attribute);\r
+\r
+ Index = 0;\r
+ PreviousIndex = 0;\r
+ Count = 0;\r
+ PrintWidth = 0;\r
+ CharWidth = 1;\r
+\r
+ do {\r
+ for (; (Buffer[Index] != NARROW_CHAR) && (Buffer[Index] != WIDE_CHAR) && (Buffer[Index] != 0); Index++) {\r
+ BackupBuffer[Index] = Buffer[Index];\r
+ }\r
+\r
+ if (Buffer[Index] == 0) {\r
+ break;\r
+ }\r
+ //\r
+ // Null-terminate the temporary string\r
+ //\r
+ BackupBuffer[Index] = 0;\r
+\r
+ //\r
+ // Print this out, we are about to switch widths\r
+ //\r
+ Out->OutputString (Out, &BackupBuffer[PreviousIndex]);\r
+ Count += StrLen (&BackupBuffer[PreviousIndex]);\r
+ PrintWidth += Count * CharWidth;\r
+\r
+ //\r
+ // Preserve the current index + 1, since this is where we will start printing from next\r
+ //\r
+ PreviousIndex = Index + 1;\r
+\r
+ //\r
+ // We are at a narrow or wide character directive. Set attributes and strip it and print it\r
+ //\r
+ if (Buffer[Index] == NARROW_CHAR) {\r
+ //\r
+ // Preserve bits 0 - 6 and zero out the rest\r
+ //\r
+ Out->Mode->Attribute = Out->Mode->Attribute & 0x7f;\r
+ Out->SetAttribute (Out, Out->Mode->Attribute);\r
+ CharWidth = 1;\r
+ } else {\r
+ //\r
+ // Must be wide, set bit 7 ON\r
+ //\r
+ Out->Mode->Attribute = Out->Mode->Attribute | EFI_WIDE_ATTRIBUTE;\r
+ Out->SetAttribute (Out, Out->Mode->Attribute);\r
+ CharWidth = 2;\r
+ }\r
+\r
+ Index++;\r
+\r
+ } while (Buffer[Index] != 0);\r
+\r
+ //\r
+ // We hit the end of the string - print it\r
+ //\r
+ Out->OutputString (Out, &BackupBuffer[PreviousIndex]);\r
+ Count += StrLen (&BackupBuffer[PreviousIndex]);\r
+ PrintWidth += Count * CharWidth;\r
+ if (PrintWidth < Width) {\r
+ Out->Mode->Attribute = Out->Mode->Attribute & 0x7f;\r
+ Out->SetAttribute (Out, Out->Mode->Attribute);\r
+ Out->OutputString (Out, &mSpaceBuffer[SPACE_BUFFER_SIZE - Width + PrintWidth]);\r
+ }\r
+\r
+ FreePool (Buffer);\r
+ FreePool (BackupBuffer);\r
+ return Count;\r
+}\r
+\r
+/**\r
+ Prints a formatted unicode string to the default console, at\r
+ the supplied cursor position.\r
+\r
+ @param Width Width of String to be printed.\r
+ @param Column The cursor position to print the string at.\r
+ @param Row The cursor position to print the string at.\r
+ @param Fmt Format string.\r
+ @param ... Variable argument list for format string.\r
+\r
+ @return Length of string printed to the console\r
+\r
+**/\r
+UINTN\r
+EFIAPI\r
+PrintAt (\r
+ IN UINTN Width,\r
+ IN UINTN Column,\r
+ IN UINTN Row,\r
+ IN CHAR16 *Fmt,\r
+ ...\r
+ )\r
+{\r
+ VA_LIST Args;\r
+ UINTN LengthOfPrinted;\r
+\r
+ VA_START (Args, Fmt);\r
+ LengthOfPrinted = PrintInternal (Width, Column, Row, gST->ConOut, Fmt, Args);\r
+ VA_END (Args);\r
+ return LengthOfPrinted;\r
+}\r
+\r
--- /dev/null
+/** @file\r
+\r
+ This library class defines a set of interfaces to customize Display module\r
+\r
+Copyright (c) 2013, Intel Corporation. All rights reserved.<BR>\r
+This program and the accompanying materials are licensed and made available under \r
+the terms and conditions of the BSD License that accompanies this distribution. \r
+The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php. \r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, \r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#ifndef __CUSTOMIZED_DISPLAY_LIB_INTERNAL_H__\r
+#define __CUSTOMIZED_DISPLAY_LIB_INTERNAL_H__\r
+\r
+\r
+\r
+#include <PiDxe.h>\r
+\r
+#include <Protocol/SimpleTextOut.h>\r
+#include <Protocol/SimpleTextIn.h>\r
+#include <Protocol/FormBrowser2.h>\r
+#include <Protocol/FormBrowserEx2.h>\r
+#include <Protocol/DisplayProtocol.h>\r
+#include <Protocol/DevicePath.h>\r
+#include <Protocol/UnicodeCollation.h>\r
+#include <Protocol/HiiConfigAccess.h>\r
+#include <Protocol/HiiConfigRouting.h>\r
+#include <Protocol/HiiDatabase.h>\r
+#include <Protocol/HiiString.h>\r
+#include <Protocol/UserManager.h>\r
+#include <Protocol/DevicePathFromText.h>\r
+\r
+#include <Guid/MdeModuleHii.h>\r
+#include <Guid/HiiPlatformSetupFormset.h>\r
+#include <Guid/HiiFormMapMethodGuid.h>\r
+\r
+#include <Library/PrintLib.h>\r
+#include <Library/DebugLib.h>\r
+#include <Library/BaseMemoryLib.h>\r
+#include <Library/UefiRuntimeServicesTableLib.h>\r
+#include <Library/UefiDriverEntryPoint.h>\r
+#include <Library/UefiBootServicesTableLib.h>\r
+#include <Library/BaseLib.h>\r
+#include <Library/MemoryAllocationLib.h>\r
+#include <Library/HiiLib.h>\r
+#include <Library/PcdLib.h>\r
+#include <Library/DevicePathLib.h>\r
+#include <Library/CustomizedDisplayLib.h>\r
+\r
+#include "Colors.h"\r
+\r
+\r
+\r
+#define FORMSET_CLASS_PLATFORM_SETUP 0x0001\r
+#define FORMSET_CLASS_FRONT_PAGE 0x0002\r
+\r
+\r
+#define FRONT_PAGE_HEADER_HEIGHT 6\r
+#define NONE_FRONT_PAGE_HEADER_HEIGHT 3\r
+#define FOOTER_HEIGHT 4\r
+#define STATUS_BAR_HEIGHT 1\r
+\r
+//\r
+// Screen definitions\r
+//\r
+#define BANNER_HEIGHT 6\r
+#define BANNER_COLUMNS 3\r
+#define BANNER_LEFT_COLUMN_INDENT 1\r
+\r
+//\r
+// Character definitions\r
+//\r
+#define UPPER_LOWER_CASE_OFFSET 0x20\r
+\r
+//\r
+// This is the Input Error Message\r
+//\r
+#define INPUT_ERROR 1\r
+\r
+//\r
+// This is the NV RAM update required Message\r
+//\r
+#define NV_UPDATE_REQUIRED 2\r
+\r
+typedef struct {\r
+ EFI_STRING_ID Banner[BANNER_HEIGHT][BANNER_COLUMNS];\r
+} BANNER_DATA;\r
+\r
+extern UINT16 gClassOfVfr; // Formset class information\r
+extern BANNER_DATA *gBannerData;\r
+extern EFI_SCREEN_DESCRIPTOR gScreenDimensions;\r
+extern UINTN gFooterHeight;\r
+\r
+//\r
+// Browser Global Strings\r
+//\r
+extern CHAR16 *gEnterString;\r
+extern CHAR16 *gEnterCommitString;\r
+extern CHAR16 *gEnterEscapeString;\r
+extern CHAR16 *gEscapeString;\r
+extern CHAR16 *gMoveHighlight;\r
+extern CHAR16 *gDecNumericInput;\r
+extern CHAR16 *gHexNumericInput;\r
+extern CHAR16 *gToggleCheckBox;\r
+extern CHAR16 *gLibEmptyString;\r
+extern CHAR16 *gAreYouSure;\r
+extern CHAR16 *gYesResponse;\r
+extern CHAR16 *gNoResponse;\r
+extern CHAR16 *gPlusString;\r
+extern CHAR16 *gMinusString;\r
+extern CHAR16 *gAdjustNumber;\r
+extern CHAR16 *gSaveChanges;\r
+extern CHAR16 *gNvUpdateMessage;\r
+extern CHAR16 *gInputErrorMessage;\r
+/**\r
+\r
+ Print banner info for front page.\r
+\r
+ @param[in] FormData Form Data to be shown in Page\r
+ \r
+**/\r
+VOID\r
+PrintBannerInfo ( \r
+ IN FORM_DISPLAY_ENGINE_FORM *FormData\r
+ );\r
+\r
+/**\r
+ Print framework and form title for a page.\r
+\r
+ @param[in] FormData Form Data to be shown in Page\r
+**/\r
+VOID\r
+PrintFramework (\r
+ IN FORM_DISPLAY_ENGINE_FORM *FormData\r
+ );\r
+\r
+/**\r
+ Validate the input screen diemenstion info.\r
+\r
+ @param FormData The input form data info.\r
+\r
+ @return EFI_SUCCESS The input screen info is acceptable.\r
+ @return EFI_INVALID_PARAMETER The input screen info is not acceptable.\r
+\r
+**/\r
+EFI_STATUS \r
+ScreenDiemensionInfoValidate (\r
+ IN FORM_DISPLAY_ENGINE_FORM *FormData\r
+ );\r
+\r
+/**\r
+ Get the string based on the StringId and HII Package List Handle.\r
+\r
+ @param Token The String's ID.\r
+ @param HiiHandle The package list in the HII database to search for\r
+ the specified string.\r
+\r
+ @return The output string.\r
+\r
+**/\r
+CHAR16 *\r
+LibGetToken (\r
+ IN EFI_STRING_ID Token,\r
+ IN EFI_HII_HANDLE HiiHandle\r
+ );\r
+\r
+/**\r
+ Count the storage space of a Unicode string.\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
+\r
+ If String is NULL, then ASSERT ().\r
+\r
+ @param String The input string to be counted.\r
+\r
+ @return Storage space for the input string.\r
+\r
+**/\r
+UINTN\r
+LibGetStringWidth (\r
+ IN CHAR16 *String\r
+ );\r
+\r
+/**\r
+ Show all registered HotKey help strings on bottom Rows.\r
+\r
+ @param FormData The curent input form data info.\r
+\r
+**/\r
+VOID\r
+PrintHotKeyHelpString (\r
+ IN FORM_DISPLAY_ENGINE_FORM *FormData\r
+ );\r
+ \r
+/**\r
+ Get step info from numeric opcode.\r
+ \r
+ @param[in] OpCode The input numeric op code.\r
+\r
+ @return step info for this opcode.\r
+**/\r
+UINT64\r
+LibGetFieldFromNum (\r
+ IN EFI_IFR_OP_HEADER *OpCode\r
+ );\r
+\r
+/**\r
+ Initialize the HII String Token to the correct values.\r
+\r
+**/\r
+VOID\r
+InitializeLibStrings (\r
+ VOID\r
+ );\r
+\r
+/**\r
+ Free the HII String.\r
+\r
+**/\r
+VOID\r
+FreeLibStrings (\r
+ VOID\r
+ );\r
+\r
+/**\r
+ Wait for a key to be pressed by user.\r
+\r
+ @param Key The key which is pressed by user.\r
+\r
+ @retval EFI_SUCCESS The function always completed successfully.\r
+\r
+**/\r
+EFI_STATUS\r
+WaitForKeyStroke (\r
+ OUT EFI_INPUT_KEY *Key\r
+ );\r
+\r
+/**\r
+ Set Buffer to Value for Size bytes.\r
+\r
+ @param Buffer Memory to set.\r
+ @param Size Number of bytes to set\r
+ @param Value Value of the set operation.\r
+\r
+**/\r
+VOID\r
+LibSetUnicodeMem (\r
+ IN VOID *Buffer,\r
+ IN UINTN Size,\r
+ IN CHAR16 Value\r
+ );\r
+\r
+/**\r
+ Prints a formatted unicode string to the default console, at\r
+ the supplied cursor position.\r
+\r
+ @param Width Width of String to be printed.\r
+ @param Column The cursor position to print the string at.\r
+ @param Row The cursor position to print the string at.\r
+ @param Fmt Format string.\r
+ @param ... Variable argument list for format string.\r
+\r
+ @return Length of string printed to the console\r
+\r
+**/\r
+UINTN\r
+EFIAPI\r
+PrintAt (\r
+ IN UINTN Width,\r
+ IN UINTN Column,\r
+ IN UINTN Row,\r
+ IN CHAR16 *Fmt,\r
+ ...\r
+ );\r
+\r
+/**\r
+ Process some op codes which is out side of current form.\r
+ \r
+ @param FormData Pointer to the form data.\r
+\r
+**/\r
+VOID\r
+ProcessExternedOpcode (\r
+ IN FORM_DISPLAY_ENGINE_FORM *FormData\r
+ );\r
+\r
+#endif\r
#\r
CpuExceptionHandlerLib|Include/Library/CpuExceptionHandlerLib.h\r
\r
+ ## @libraryclass Provides platform specific display interface.\r
+ #\r
+ CustomizedDisplayLib|Include/Library/CustomizedDisplayLib.h\r
+\r
[Guids]\r
## MdeModule package token space guid\r
# Include/Guid/MdeModulePkgTokenSpace.h\r
## Include/Protocol/BootLogo.h\r
gEfiBootLogoProtocolGuid = { 0xcdea2bd3, 0xfc25, 0x4c1c, { 0xb9, 0x7c, 0xb3, 0x11, 0x86, 0x6, 0x49, 0x90 } }\r
\r
+ ## Include/Protocol/DisplayProtocol.h\r
+ gEdkiiFormDisplayEngineProtocolGuid = { 0x9bbe29e9, 0xfda1, 0x41ec, { 0xad, 0x52, 0x45, 0x22, 0x13, 0x74, 0x2d, 0x2e } }\r
+\r
+ ## Include/Protocol/FormBrowserEx2.h\r
+ gEdkiiFormBrowserEx2ProtocolGuid = { 0xa770c357, 0xb693, 0x4e6d, { 0xa6, 0xcf, 0xd2, 0x1c, 0x72, 0x8e, 0x55, 0xb } }\r
+\r
[PcdsFeatureFlag]\r
## Indicate whether platform can support update capsule across a system reset\r
gEfiMdeModulePkgTokenSpaceGuid.PcdSupportUpdateCapsuleReset|FALSE|BOOLEAN|0x0001001d\r
CapsuleLib|MdeModulePkg/Library/DxeCapsuleLibNull/DxeCapsuleLibNull.inf\r
PcdLib|MdePkg/Library/BasePcdLibNull/BasePcdLibNull.inf\r
PalLib|MdePkg/Library/BasePalLibNull/BasePalLibNull.inf\r
+ CustomizedDisplayLib|MdeModulePkg/Library/CustomizedDisplayLib/CustomizedDisplayLib.inf\r
#\r
# Misc\r
#\r
\r
MdeModulePkg/Universal/SecurityStubDxe/SecurityStubDxe.inf\r
MdeModulePkg/Universal/SetupBrowserDxe/SetupBrowserDxe.inf\r
+ MdeModulePkg/Universal/DisplayEngineDxe/DisplayEngineDxe.inf\r
MdeModulePkg/Application/VariableInfo/VariableInfo.inf\r
MdeModulePkg/Universal/FaultTolerantWritePei/FaultTolerantWritePei.inf\r
MdeModulePkg/Universal/Variable/Pei/VariablePei.inf\r
--- /dev/null
+## @file\r
+# The DXE driver produces FORM BROWSER protocols defined in UEFI HII 2.1 specificatin.\r
+#\r
+# Copyright (c) 2007 - 2013, Intel Corporation. All rights reserved.<BR>\r
+#\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
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+#\r
+#\r
+##\r
+\r
+[Defines]\r
+ INF_VERSION = 0x00010005\r
+ BASE_NAME = DisplayEngine\r
+ FILE_GUID = E660EA85-058E-4b55-A54B-F02F83A24707\r
+ MODULE_TYPE = DXE_DRIVER\r
+ VERSION_STRING = 1.0\r
+ ENTRY_POINT = InitializeDisplayEngine\r
+ UNLOAD_IMAGE = UnloadDisplayEngine\r
+#\r
+# The following information is for reference only and not required by the build tools.\r
+#\r
+# VALID_ARCHITECTURES = IA32 X64 IPF EBC\r
+#\r
+\r
+[Sources]\r
+ FormDisplayStr.uni\r
+ FormDisplay.c\r
+ FormDisplay.h\r
+ ProcessOptions.c\r
+ InputHandler.c\r
+ \r
+[Packages]\r
+ MdePkg/MdePkg.dec\r
+ MdeModulePkg/MdeModulePkg.dec\r
+ \r
+[LibraryClasses]\r
+ UefiDriverEntryPoint\r
+ UefiBootServicesTableLib\r
+ DebugLib\r
+ BaseMemoryLib\r
+ BaseLib\r
+ PrintLib\r
+ HiiLib\r
+ MemoryAllocationLib\r
+ CustomizedDisplayLib\r
+\r
+[Protocols]\r
+ gEdkiiFormDisplayEngineProtocolGuid\r
+ gEdkiiFormBrowserEx2ProtocolGuid\r
+\r
+[Guids]\r
+ gEfiIfrTianoGuid ## CONSUMES ## GUID \r
+ \r
+[Depex]\r
+ gEfiHiiDatabaseProtocolGuid AND gEfiHiiConfigRoutingProtocolGuid AND gEdkiiFormBrowserEx2ProtocolGuid\r
+ \r
+[FeaturePcd]\r
+ gEfiMdeModulePkgTokenSpaceGuid.PcdBrowserGrayOutTextStatement ## CONSUMES\r
+ gEfiMdeModulePkgTokenSpaceGuid.PcdBrowerGrayOutReadOnlyMenu ## CONSUMES\r
+\r
--- /dev/null
+/** @file\r
+Entry and initialization module for the browser.\r
+\r
+Copyright (c) 2007 - 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
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#include "FormDisplay.h"\r
+\r
+//\r
+// Search table for UiDisplayMenu()\r
+//\r
+SCAN_CODE_TO_SCREEN_OPERATION gScanCodeToOperation[] = {\r
+ {\r
+ SCAN_UP,\r
+ UiUp,\r
+ },\r
+ {\r
+ SCAN_DOWN,\r
+ UiDown,\r
+ },\r
+ {\r
+ SCAN_PAGE_UP,\r
+ UiPageUp,\r
+ },\r
+ {\r
+ SCAN_PAGE_DOWN,\r
+ UiPageDown,\r
+ },\r
+ {\r
+ SCAN_ESC,\r
+ UiReset,\r
+ },\r
+ {\r
+ SCAN_LEFT,\r
+ UiLeft,\r
+ },\r
+ {\r
+ SCAN_RIGHT,\r
+ UiRight,\r
+ }\r
+};\r
+\r
+UINTN mScanCodeNumber = sizeof (gScanCodeToOperation) / sizeof (gScanCodeToOperation[0]);\r
+\r
+SCREEN_OPERATION_T0_CONTROL_FLAG gScreenOperationToControlFlag[] = {\r
+ {\r
+ UiNoOperation,\r
+ CfUiNoOperation,\r
+ },\r
+ {\r
+ UiSelect,\r
+ CfUiSelect,\r
+ },\r
+ {\r
+ UiUp,\r
+ CfUiUp,\r
+ },\r
+ {\r
+ UiDown,\r
+ CfUiDown,\r
+ },\r
+ {\r
+ UiLeft,\r
+ CfUiLeft,\r
+ },\r
+ {\r
+ UiRight,\r
+ CfUiRight,\r
+ },\r
+ {\r
+ UiReset,\r
+ CfUiReset,\r
+ },\r
+ {\r
+ UiPageUp,\r
+ CfUiPageUp,\r
+ },\r
+ {\r
+ UiPageDown,\r
+ CfUiPageDown\r
+ }, \r
+ {\r
+ UiHotKey,\r
+ CfUiHotKey\r
+ }\r
+};\r
+\r
+EFI_GUID gDisplayEngineGuid = {\r
+ 0xE38C1029, 0xE38F, 0x45b9, {0x8F, 0x0D, 0xE2, 0xE6, 0x0B, 0xC9, 0xB2, 0x62}\r
+};\r
+\r
+FORM_ENTRY_INFO gFormEntryInfo;\r
+UINTN gSequence;\r
+EFI_SCREEN_DESCRIPTOR gStatementDimensions;\r
+BOOLEAN mStatementLayoutIsChanged = TRUE;\r
+USER_INPUT *gUserInput;\r
+FORM_DISPLAY_ENGINE_FORM *gFormData;\r
+EFI_HII_HANDLE gHiiHandle;\r
+UINT16 gDirection;\r
+LIST_ENTRY gMenuOption;\r
+DISPLAY_HIGHLIGHT_MENU_INFO gHighligthMenuInfo = {0};\r
+BOOLEAN mIsFirstForm = TRUE;\r
+FORM_ENTRY_INFO gOldFormEntry = {0};\r
+\r
+//\r
+// Browser Global Strings\r
+//\r
+CHAR16 *gFormNotFound;\r
+CHAR16 *gNoSubmitIf;\r
+CHAR16 *gBrwoserError;\r
+CHAR16 *gSaveFailed;\r
+CHAR16 *gPromptForData;\r
+CHAR16 *gPromptForPassword;\r
+CHAR16 *gPromptForNewPassword;\r
+CHAR16 *gConfirmPassword;\r
+CHAR16 *gConfirmError;\r
+CHAR16 *gPassowordInvalid;\r
+CHAR16 *gPressEnter;\r
+CHAR16 *gEmptyString;\r
+CHAR16 *gMiniString;\r
+CHAR16 *gOptionMismatch;\r
+CHAR16 *gFormSuppress;\r
+CHAR16 *gProtocolNotFound;\r
+\r
+CHAR16 gPromptBlockWidth;\r
+CHAR16 gOptionBlockWidth;\r
+CHAR16 gHelpBlockWidth;\r
+CHAR16 *mUnknownString;\r
+\r
+FORM_DISPLAY_DRIVER_PRIVATE_DATA mPrivateData = {\r
+ FORM_DISPLAY_DRIVER_SIGNATURE,\r
+ NULL,\r
+ {\r
+ FormDisplay,\r
+ DriverClearDisplayPage,\r
+ ConfirmDataChange\r
+ }\r
+};\r
+\r
+\r
+/**\r
+ Get the string based on the StringId and HII Package List Handle.\r
+\r
+ @param Token The String's ID.\r
+ @param HiiHandle The package list in the HII database to search for\r
+ the specified string.\r
+\r
+ @return The output string.\r
+\r
+**/\r
+CHAR16 *\r
+GetToken (\r
+ IN EFI_STRING_ID Token,\r
+ IN EFI_HII_HANDLE HiiHandle\r
+ )\r
+{\r
+ EFI_STRING String;\r
+\r
+ String = HiiGetString (HiiHandle, Token, NULL);\r
+ if (String == NULL) {\r
+ String = AllocateCopyPool (StrSize (mUnknownString), mUnknownString);\r
+ ASSERT (String != NULL);\r
+ }\r
+\r
+ return (CHAR16 *) String;\r
+}\r
+\r
+\r
+/**\r
+ Initialize the HII String Token to the correct values.\r
+\r
+**/\r
+VOID\r
+InitializeDisplayStrings (\r
+ VOID\r
+ )\r
+{\r
+ mUnknownString = GetToken (STRING_TOKEN (UNKNOWN_STRING), gHiiHandle);\r
+ gSaveFailed = GetToken (STRING_TOKEN (SAVE_FAILED), 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
+ gMiniString = GetToken (STRING_TOKEN (MINI_STRING), gHiiHandle);\r
+ gOptionMismatch = GetToken (STRING_TOKEN (OPTION_MISMATCH), gHiiHandle);\r
+ gFormSuppress = GetToken (STRING_TOKEN (FORM_SUPPRESSED), gHiiHandle);\r
+ gProtocolNotFound = GetToken (STRING_TOKEN (PROTOCOL_NOT_FOUND), gHiiHandle);\r
+ gFormNotFound = GetToken (STRING_TOKEN (STATUS_BROWSER_FORM_NOT_FOUND), gHiiHandle);\r
+ gNoSubmitIf = GetToken (STRING_TOKEN (STATUS_BROWSER_NO_SUBMIT_IF), gHiiHandle);\r
+ gBrwoserError = GetToken (STRING_TOKEN (STATUS_BROWSER_ERROR), gHiiHandle);\r
+}\r
+\r
+/**\r
+ Free up the resource allocated for all strings required\r
+ by Setup Browser.\r
+\r
+**/\r
+VOID\r
+FreeDisplayStrings (\r
+ VOID\r
+ )\r
+{\r
+ FreePool (mUnknownString);\r
+ FreePool (gEmptyString);\r
+ FreePool (gSaveFailed);\r
+ FreePool (gPromptForData);\r
+ FreePool (gPromptForPassword);\r
+ FreePool (gPromptForNewPassword);\r
+ FreePool (gConfirmPassword);\r
+ FreePool (gConfirmError);\r
+ FreePool (gPassowordInvalid);\r
+ FreePool (gPressEnter);\r
+ FreePool (gMiniString);\r
+ FreePool (gOptionMismatch);\r
+ FreePool (gFormSuppress);\r
+ FreePool (gProtocolNotFound);\r
+ FreePool (gBrwoserError);\r
+ FreePool (gNoSubmitIf);\r
+ FreePool (gFormNotFound);\r
+}\r
+\r
+/**\r
+ Get prompt string id from the opcode data buffer.\r
+\r
+ @param OpCode The input opcode buffer.\r
+\r
+ @return The prompt string id.\r
+\r
+**/\r
+EFI_STRING_ID\r
+GetPrompt (\r
+ IN EFI_IFR_OP_HEADER *OpCode\r
+ )\r
+{\r
+ EFI_IFR_STATEMENT_HEADER *Header;\r
+\r
+ if (OpCode->Length <= sizeof (EFI_IFR_OP_HEADER)) {\r
+ return 0;\r
+ }\r
+\r
+ Header = (EFI_IFR_STATEMENT_HEADER *) (OpCode + 1);\r
+\r
+ return Header->Prompt;\r
+}\r
+\r
+/**\r
+ Get the supported width for a particular op-code\r
+\r
+ @param Statement The curent statement.\r
+\r
+ @return Returns the number of CHAR16 characters that is support.\r
+\r
+**/\r
+UINT16\r
+GetWidth (\r
+ IN FORM_DISPLAY_ENGINE_STATEMENT *Statement\r
+ )\r
+{\r
+ CHAR16 *String;\r
+ UINTN Size;\r
+ UINT16 Width;\r
+ EFI_IFR_TEXT *TestOp;\r
+\r
+ Size = 0;\r
+\r
+ //\r
+ // See if the second text parameter is really NULL\r
+ //\r
+ if (Statement->OpCode->OpCode == EFI_IFR_TEXT_OP) {\r
+ TestOp = (EFI_IFR_TEXT *) Statement->OpCode;\r
+ if (TestOp->TextTwo != 0) {\r
+ String = GetToken (TestOp->TextTwo, gFormData->HiiHandle);\r
+ Size = StrLen (String);\r
+ FreePool (String);\r
+ }\r
+ }\r
+\r
+ if ((Statement->OpCode->OpCode == EFI_IFR_SUBTITLE_OP) ||\r
+ (Statement->OpCode->OpCode == EFI_IFR_REF_OP) ||\r
+ (Statement->OpCode->OpCode == EFI_IFR_PASSWORD_OP) ||\r
+ (Statement->OpCode->OpCode == EFI_IFR_ACTION_OP) ||\r
+ (Statement->OpCode->OpCode == EFI_IFR_RESET_BUTTON_OP) ||\r
+ //\r
+ // Allow a wide display if text op-code and no secondary text op-code\r
+ //\r
+ ((Statement->OpCode->OpCode == EFI_IFR_TEXT_OP) && (Size == 0))\r
+ ) {\r
+ Width = (UINT16) (gPromptBlockWidth + gOptionBlockWidth);\r
+ } else {\r
+ Width = (UINT16) gPromptBlockWidth;\r
+ }\r
+\r
+ return (UINT16) (Width - LEFT_SKIPPED_COLUMNS);\r
+}\r
+\r
+/**\r
+ Will copy LineWidth amount of a string in the OutputString buffer and return the\r
+ number of CHAR16 characters that were copied into the OutputString buffer.\r
+ The output string format is:\r
+ Glyph Info + String info + '\0'.\r
+\r
+ In the code, it deals \r,\n,\r\n same as \n\r, also it not process the \r or \g.\r
+\r
+ @param InputString String description for this option.\r
+ @param LineWidth Width of the desired string to extract in CHAR16\r
+ characters\r
+ @param GlyphWidth The glyph width of the begin of the char in the string.\r
+ @param Index Where in InputString to start the copy process\r
+ @param OutputString Buffer to copy the string into\r
+\r
+ @return Returns the number of CHAR16 characters that were copied into the OutputString \r
+ buffer, include extra glyph info and '\0' info.\r
+\r
+**/\r
+UINT16\r
+GetLineByWidth (\r
+ IN CHAR16 *InputString,\r
+ IN UINT16 LineWidth,\r
+ IN OUT UINT16 *GlyphWidth,\r
+ IN OUT UINTN *Index,\r
+ OUT CHAR16 **OutputString\r
+ )\r
+{\r
+ UINT16 StrOffset;\r
+ UINT16 GlyphOffset;\r
+ UINT16 OriginalGlyphWidth;\r
+ BOOLEAN ReturnFlag;\r
+ UINT16 LastSpaceOffset;\r
+ UINT16 LastGlyphWidth;\r
+\r
+ if (InputString == NULL || Index == NULL || OutputString == NULL) {\r
+ return 0;\r
+ }\r
+\r
+ if (LineWidth == 0 || *GlyphWidth == 0) {\r
+ return 0;\r
+ }\r
+\r
+ //\r
+ // Save original glyph width.\r
+ //\r
+ OriginalGlyphWidth = *GlyphWidth;\r
+ LastGlyphWidth = OriginalGlyphWidth;\r
+ ReturnFlag = FALSE;\r
+ LastSpaceOffset = 0;\r
+\r
+ //\r
+ // NARROW_CHAR can not be printed in screen, so if a line only contain the two CHARs: 'NARROW_CHAR + CHAR_CARRIAGE_RETURN' , it is a empty line in Screen.\r
+ // To avoid displaying this empty line in screen, just skip the two CHARs here.\r
+ //\r
+ if ((InputString[*Index] == NARROW_CHAR) && (InputString[*Index + 1] == CHAR_CARRIAGE_RETURN)) {\r
+ *Index = *Index + 2;\r
+ }\r
+\r
+ //\r
+ // Fast-forward the string and see if there is a carriage-return in the string\r
+ //\r
+ for (StrOffset = 0, GlyphOffset = 0; GlyphOffset <= LineWidth; StrOffset++) {\r
+ switch (InputString[*Index + StrOffset]) {\r
+ case NARROW_CHAR:\r
+ *GlyphWidth = 1;\r
+ break;\r
+\r
+ case WIDE_CHAR:\r
+ *GlyphWidth = 2;\r
+ break;\r
+\r
+ case CHAR_CARRIAGE_RETURN:\r
+ case CHAR_LINEFEED:\r
+ case CHAR_NULL:\r
+ ReturnFlag = TRUE;\r
+ break;\r
+\r
+ default:\r
+ GlyphOffset = GlyphOffset + *GlyphWidth;\r
+\r
+ //\r
+ // Record the last space info in this line. Will be used in rewind.\r
+ //\r
+ if ((InputString[*Index + StrOffset] == CHAR_SPACE) && (GlyphOffset <= LineWidth)) {\r
+ LastSpaceOffset = StrOffset;\r
+ LastGlyphWidth = *GlyphWidth;\r
+ }\r
+ break;\r
+ }\r
+\r
+ if (ReturnFlag) {\r
+ break;\r
+ }\r
+ } \r
+\r
+ //\r
+ // Rewind the string from the maximum size until we see a space to break the line\r
+ //\r
+ if (GlyphOffset > LineWidth) {\r
+ //\r
+ // Rewind the string to last space char in this line.\r
+ //\r
+ if (LastSpaceOffset != 0) {\r
+ StrOffset = LastSpaceOffset;\r
+ *GlyphWidth = LastGlyphWidth;\r
+ } else {\r
+ //\r
+ // Roll back to last char in the line width.\r
+ //\r
+ StrOffset--;\r
+ }\r
+ }\r
+\r
+ //\r
+ // The CHAR_NULL has process last time, this time just return 0 to stand for the end.\r
+ //\r
+ if (StrOffset == 0 && (InputString[*Index + StrOffset] == CHAR_NULL)) {\r
+ return 0;\r
+ }\r
+\r
+ //\r
+ // Need extra glyph info and '\0' info, so +2.\r
+ //\r
+ *OutputString = AllocateZeroPool (((UINTN) (StrOffset + 2) * sizeof(CHAR16)));\r
+ if (*OutputString == NULL) {\r
+ return 0;\r
+ }\r
+\r
+ //\r
+ // Save the glyph info at the begin of the string, will used by Print function.\r
+ //\r
+ if (OriginalGlyphWidth == 1) {\r
+ *(*OutputString) = NARROW_CHAR;\r
+ } else {\r
+ *(*OutputString) = WIDE_CHAR;\r
+ }\r
+\r
+ CopyMem ((*OutputString) + 1, &InputString[*Index], StrOffset * sizeof(CHAR16));\r
+\r
+ if (InputString[*Index + StrOffset] == CHAR_SPACE) {\r
+ //\r
+ // Skip the space info at the begin of next line.\r
+ // \r
+ *Index = (UINT16) (*Index + StrOffset + 1);\r
+ } else if (InputString[*Index + StrOffset] == CHAR_LINEFEED) {\r
+ //\r
+ // Skip the /n or /n/r info.\r
+ //\r
+ if (InputString[*Index + StrOffset + 1] == CHAR_CARRIAGE_RETURN) {\r
+ *Index = (UINT16) (*Index + StrOffset + 2);\r
+ } else {\r
+ *Index = (UINT16) (*Index + StrOffset + 1);\r
+ }\r
+ } else if (InputString[*Index + StrOffset] == CHAR_CARRIAGE_RETURN) {\r
+ //\r
+ // Skip the /r or /r/n info.\r
+ // \r
+ if (InputString[*Index + StrOffset + 1] == CHAR_LINEFEED) {\r
+ *Index = (UINT16) (*Index + StrOffset + 2);\r
+ } else {\r
+ *Index = (UINT16) (*Index + StrOffset + 1);\r
+ }\r
+ } else {\r
+ *Index = (UINT16) (*Index + StrOffset);\r
+ }\r
+\r
+ //\r
+ // Include extra glyph info and '\0' info, so +2.\r
+ //\r
+ return StrOffset + 2;\r
+}\r
+\r
+/**\r
+ Add one menu option by specified description and context.\r
+\r
+ @param Statement Statement of this Menu Option.\r
+ @param MenuItemCount The index for this Option in the Menu.\r
+ @param NestIn Whether this statement is nest in another statement.\r
+\r
+**/\r
+VOID\r
+UiAddMenuOption (\r
+ IN FORM_DISPLAY_ENGINE_STATEMENT *Statement,\r
+ IN UINT16 *MenuItemCount,\r
+ IN BOOLEAN NestIn\r
+ )\r
+{\r
+ UI_MENU_OPTION *MenuOption;\r
+ UINTN Index;\r
+ UINTN Count;\r
+ CHAR16 *String;\r
+ UINT16 NumberOfLines;\r
+ UINT16 GlyphWidth;\r
+ UINT16 Width;\r
+ UINTN ArrayEntry;\r
+ CHAR16 *OutputString;\r
+ EFI_STRING_ID PromptId;\r
+\r
+ NumberOfLines = 1;\r
+ ArrayEntry = 0;\r
+ GlyphWidth = 1;\r
+ Count = 1;\r
+ MenuOption = NULL;\r
+\r
+ PromptId = GetPrompt (Statement->OpCode);\r
+ ASSERT (PromptId != 0);\r
+\r
+ String = GetToken (PromptId, gFormData->HiiHandle);\r
+ ASSERT (String != NULL);\r
+\r
+ Width = GetWidth (Statement);\r
+ for (; GetLineByWidth (String, Width, &GlyphWidth,&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 (&String[ArrayEntry]) != 0) {\r
+ NumberOfLines++;\r
+ }\r
+ FreePool (OutputString);\r
+ }\r
+\r
+ if (Statement->OpCode->OpCode == EFI_IFR_DATE_OP || Statement->OpCode->OpCode == EFI_IFR_TIME_OP) {\r
+ //\r
+ // Add three MenuOptions for Date/Time\r
+ // Data format : [01/02/2004] [11:22:33]\r
+ // Line number : 0 0 1 0 0 1\r
+ //\r
+ NumberOfLines = 0;\r
+ Count = 3;\r
+ }\r
+\r
+ for (Index = 0; Index < Count; Index++) {\r
+ MenuOption = AllocateZeroPool (sizeof (UI_MENU_OPTION));\r
+ ASSERT (MenuOption);\r
+\r
+ MenuOption->Signature = UI_MENU_OPTION_SIGNATURE;\r
+ MenuOption->Description = String;\r
+ MenuOption->Handle = gFormData->HiiHandle;\r
+ MenuOption->ThisTag = Statement;\r
+ MenuOption->NestInStatement = NestIn;\r
+ MenuOption->EntryNumber = *MenuItemCount;\r
+\r
+ if (Index == 2) {\r
+ //\r
+ // Override LineNumber for the MenuOption in Date/Time sequence\r
+ //\r
+ MenuOption->Skip = 1;\r
+ } else {\r
+ MenuOption->Skip = NumberOfLines;\r
+ }\r
+ MenuOption->Sequence = Index;\r
+\r
+ if ((Statement->Attribute & HII_DISPLAY_GRAYOUT) != 0) {\r
+ MenuOption->GrayOut = TRUE;\r
+ } else {\r
+ MenuOption->GrayOut = FALSE;\r
+ }\r
+\r
+ if ((Statement->Attribute & HII_DISPLAY_LOCK) != 0 || (gFormData->Attribute & HII_DISPLAY_LOCK) != 0) {\r
+ MenuOption->GrayOut = TRUE;\r
+ }\r
+\r
+ //\r
+ // If the form or the question has the lock attribute, deal same as grayout.\r
+ //\r
+ if ((gFormData->Attribute & HII_DISPLAY_LOCK) != 0 || (Statement->Attribute & HII_DISPLAY_LOCK) != 0) {\r
+ MenuOption->GrayOut = TRUE;\r
+ }\r
+\r
+ switch (Statement->OpCode->OpCode) {\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
+ case EFI_IFR_CHECKBOX_OP:\r
+ case EFI_IFR_PASSWORD_OP:\r
+ case EFI_IFR_STRING_OP:\r
+ //\r
+ // User could change the value of these items\r
+ //\r
+ MenuOption->IsQuestion = TRUE;\r
+ break;\r
+ case EFI_IFR_TEXT_OP:\r
+ if (FeaturePcdGet (PcdBrowserGrayOutTextStatement)) {\r
+ //\r
+ // Initializing GrayOut option as TRUE for Text setup options \r
+ // so that those options will be Gray in colour and un selectable.\r
+ //\r
+ MenuOption->GrayOut = TRUE;\r
+ }\r
+ break;\r
+ default:\r
+ MenuOption->IsQuestion = FALSE;\r
+ break;\r
+ }\r
+\r
+ if ((Statement->Attribute & HII_DISPLAY_READONLY) != 0) {\r
+ MenuOption->ReadOnly = TRUE;\r
+ if (FeaturePcdGet (PcdBrowerGrayOutReadOnlyMenu)) {\r
+ MenuOption->GrayOut = TRUE;\r
+ }\r
+ }\r
+\r
+ InsertTailList (&gMenuOption, &MenuOption->Link);\r
+ }\r
+\r
+ (*MenuItemCount)++;\r
+}\r
+\r
+/**\r
+ Create the menu list base on the form data info.\r
+\r
+**/\r
+VOID\r
+ConvertStatementToMenu (\r
+ VOID\r
+ )\r
+{\r
+ UINT16 MenuItemCount;\r
+ LIST_ENTRY *Link;\r
+ LIST_ENTRY *NestLink;\r
+ FORM_DISPLAY_ENGINE_STATEMENT *Statement;\r
+ FORM_DISPLAY_ENGINE_STATEMENT *NestStatement;\r
+\r
+ MenuItemCount = 0;\r
+ InitializeListHead (&gMenuOption);\r
+\r
+ Link = GetFirstNode (&gFormData->StatementListHead);\r
+ while (!IsNull (&gFormData->StatementListHead, Link)) {\r
+ Statement = FORM_DISPLAY_ENGINE_STATEMENT_FROM_LINK (Link);\r
+ Link = GetNextNode (&gFormData->StatementListHead, Link);\r
+\r
+ //\r
+ // Skip the opcode not recognized by Display core.\r
+ //\r
+ if (Statement->OpCode->OpCode == EFI_IFR_GUID_OP) {\r
+ continue;\r
+ }\r
+\r
+ UiAddMenuOption (Statement, &MenuItemCount, FALSE);\r
+\r
+ //\r
+ // Check the statement nest in this host statement.\r
+ //\r
+ NestLink = GetFirstNode (&Statement->NestStatementList);\r
+ while (!IsNull (&Statement->NestStatementList, NestLink)) {\r
+ NestStatement = FORM_DISPLAY_ENGINE_STATEMENT_FROM_LINK (NestLink);\r
+ NestLink = GetNextNode (&Statement->NestStatementList, NestLink);\r
+\r
+ UiAddMenuOption (NestStatement, &MenuItemCount, TRUE);\r
+ }\r
+ }\r
+}\r
+\r
+/**\r
+ Count the storage space of a Unicode string.\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
+\r
+ If String is NULL, then ASSERT ().\r
+\r
+ @param String The input string to be counted.\r
+\r
+ @return Storage space for the input string.\r
+\r
+**/\r
+UINTN\r
+GetStringWidth (\r
+ IN CHAR16 *String\r
+ )\r
+{\r
+ UINTN Index;\r
+ UINTN Count;\r
+ UINTN IncrementValue;\r
+\r
+ ASSERT (String != NULL);\r
+ if (String == NULL) {\r
+ return 0;\r
+ }\r
+\r
+ Index = 0;\r
+ Count = 0;\r
+ IncrementValue = 1;\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
+\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
+ //\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
+ }\r
+ } while (String[Index] != 0);\r
+\r
+ //\r
+ // Increment by one to include the null-terminator in the size\r
+ //\r
+ Count++;\r
+\r
+ return Count * sizeof (CHAR16);\r
+}\r
+\r
+/**\r
+ Base on the input option string to update the skip value for a menu option.\r
+\r
+ @param MenuOption The MenuOption to be checked.\r
+ @param OptionString The input option string.\r
+\r
+**/\r
+VOID\r
+UpdateSkipInfoForMenu (\r
+ IN UI_MENU_OPTION *MenuOption,\r
+ IN CHAR16 *OptionString\r
+ )\r
+{\r
+ UINTN Index;\r
+ UINT16 Width;\r
+ UINTN Row;\r
+ CHAR16 *OutputString;\r
+ UINT16 GlyphWidth;\r
+\r
+ Width = (UINT16) gOptionBlockWidth;\r
+ GlyphWidth = 1;\r
+ Row = 1;\r
+\r
+ for (Index = 0; GetLineByWidth (OptionString, Width, &GlyphWidth, &Index, &OutputString) != 0x0000;) {\r
+ if (StrLen (&OptionString[Index]) != 0) {\r
+ Row++;\r
+ }\r
+\r
+ FreePool (OutputString);\r
+ }\r
+\r
+ if ((Row > MenuOption->Skip) && \r
+ (MenuOption->ThisTag->OpCode->OpCode != EFI_IFR_DATE_OP) && \r
+ (MenuOption->ThisTag->OpCode->OpCode != EFI_IFR_TIME_OP)) {\r
+ MenuOption->Skip = Row;\r
+ }\r
+}\r
+\r
+/**\r
+ Update display lines for a Menu Option.\r
+\r
+ @param MenuOption The MenuOption to be checked.\r
+\r
+**/\r
+VOID\r
+UpdateOptionSkipLines (\r
+ IN UI_MENU_OPTION *MenuOption\r
+ )\r
+{\r
+ CHAR16 *OptionString;\r
+\r
+ OptionString = NULL;\r
+\r
+ ProcessOptions (MenuOption, FALSE, &OptionString, TRUE);\r
+ if (OptionString != NULL) {\r
+ UpdateSkipInfoForMenu (MenuOption, OptionString);\r
+\r
+ FreePool (OptionString);\r
+ }\r
+\r
+ if ((MenuOption->ThisTag->OpCode->OpCode == EFI_IFR_TEXT_OP) && (((EFI_IFR_TEXT*)MenuOption->ThisTag->OpCode)->TextTwo != 0)) {\r
+ OptionString = GetToken (((EFI_IFR_TEXT*)MenuOption->ThisTag->OpCode)->TextTwo, gFormData->HiiHandle);\r
+\r
+ if (OptionString != NULL) {\r
+ UpdateSkipInfoForMenu (MenuOption, OptionString);\r
+\r
+ FreePool (OptionString);\r
+ }\r
+ }\r
+}\r
+\r
+/**\r
+ Check whether this Menu Option could be highlighted.\r
+\r
+ This is an internal function.\r
+\r
+ @param MenuOption The MenuOption to be checked.\r
+\r
+ @retval TRUE This Menu Option is selectable.\r
+ @retval FALSE This Menu Option could not be selected.\r
+\r
+**/\r
+BOOLEAN\r
+IsSelectable (\r
+ UI_MENU_OPTION *MenuOption\r
+ )\r
+{\r
+ if ((MenuOption->ThisTag->OpCode->OpCode == EFI_IFR_SUBTITLE_OP) ||\r
+ MenuOption->GrayOut || MenuOption->ReadOnly) {\r
+ return FALSE;\r
+ } else {\r
+ return TRUE;\r
+ }\r
+}\r
+\r
+/**\r
+ Move to next selectable statement.\r
+\r
+ This is an internal function.\r
+\r
+ @param GoUp The navigation direction. TRUE: up, FALSE: down.\r
+ @param CurrentPosition Current position.\r
+ @param GapToTop Gap position to top or bottom.\r
+\r
+ @return The row distance from current MenuOption to next selectable MenuOption.\r
+\r
+ @retval -1 Reach the begin of the menu, still can't find the selectable menu.\r
+ @retval Value Find the selectable menu, maybe the truly selectable, maybe the l\r
+ last menu showing at current form.\r
+\r
+**/\r
+INTN\r
+MoveToNextStatement (\r
+ IN BOOLEAN GoUp,\r
+ IN OUT LIST_ENTRY **CurrentPosition,\r
+ IN UINTN GapToTop\r
+ )\r
+{\r
+ INTN Distance;\r
+ LIST_ENTRY *Pos;\r
+ UI_MENU_OPTION *NextMenuOption;\r
+ UI_MENU_OPTION *PreMenuOption;\r
+\r
+ Distance = 0;\r
+ Pos = *CurrentPosition;\r
+ PreMenuOption = MENU_OPTION_FROM_LINK (Pos);\r
+\r
+ while (TRUE) {\r
+ NextMenuOption = MENU_OPTION_FROM_LINK (Pos);\r
+ //\r
+ // NextMenuOption->Row == 0 means this menu has not calculate\r
+ // the NextMenuOption->Skip value yet, just calculate here.\r
+ //\r
+ if (NextMenuOption->Row == 0) {\r
+ UpdateOptionSkipLines (NextMenuOption);\r
+ }\r
+ \r
+ if (GoUp && (PreMenuOption != NextMenuOption)) {\r
+ //\r
+ // In this case, still can't find the selectable menu,\r
+ // return the last one in the showing form.\r
+ //\r
+ if ((UINTN) Distance + NextMenuOption->Skip > GapToTop) {\r
+ NextMenuOption = PreMenuOption;\r
+ break;\r
+ }\r
+\r
+ //\r
+ // Current Position doesn't need to be caculated when go up.\r
+ // Caculate distanct at first when go up\r
+ // \r
+ Distance += NextMenuOption->Skip;\r
+ }\r
+\r
+ if (IsSelectable (NextMenuOption)) {\r
+ break;\r
+ }\r
+\r
+ //\r
+ // Arrive at begin of the menu list.\r
+ //\r
+ if ((GoUp ? Pos->BackLink : Pos->ForwardLink) == &gMenuOption) {\r
+ Distance = -1;\r
+ break;\r
+ }\r
+\r
+ if (!GoUp) {\r
+ //\r
+ // In this case, still can't find the selectable menu,\r
+ // return the last one in the showing form.\r
+ //\r
+ if ((UINTN) Distance + NextMenuOption->Skip > GapToTop) {\r
+ NextMenuOption = PreMenuOption;\r
+ break;\r
+ }\r
+\r
+ Distance += NextMenuOption->Skip;\r
+ }\r
+\r
+ PreMenuOption = NextMenuOption;\r
+ Pos = (GoUp ? Pos->BackLink : Pos->ForwardLink);\r
+ }\r
+\r
+ *CurrentPosition = &NextMenuOption->Link;\r
+ return Distance;\r
+}\r
+\r
+\r
+/**\r
+ Process option string for date/time opcode.\r
+\r
+ @param MenuOption Menu option point to date/time.\r
+ @param OptionString Option string input for process.\r
+ @param AddOptCol Whether need to update MenuOption->OptCol. \r
+\r
+**/\r
+VOID \r
+ProcessStringForDateTime (\r
+ UI_MENU_OPTION *MenuOption,\r
+ CHAR16 *OptionString,\r
+ BOOLEAN AddOptCol\r
+ )\r
+{\r
+ UINTN Index;\r
+ UINTN Count;\r
+ FORM_DISPLAY_ENGINE_STATEMENT *Statement;\r
+ EFI_IFR_DATE *Date;\r
+ EFI_IFR_TIME *Time;\r
+\r
+ ASSERT (MenuOption != NULL && OptionString != NULL);\r
+ \r
+ Statement = MenuOption->ThisTag;\r
+ Date = NULL;\r
+ Time = NULL;\r
+ if (Statement->OpCode->OpCode == EFI_IFR_DATE_OP) {\r
+ Date = (EFI_IFR_DATE *) Statement->OpCode;\r
+ } else if (Statement->OpCode->OpCode == EFI_IFR_TIME_OP) {\r
+ Time = (EFI_IFR_TIME *) Statement->OpCode;\r
+ }\r
+ \r
+ //\r
+ // If leading spaces on OptionString - remove the spaces\r
+ //\r
+ for (Index = 0; OptionString[Index] == L' '; Index++) {\r
+ //\r
+ // Base on the blockspace to get the option column info.\r
+ //\r
+ if (AddOptCol) {\r
+ MenuOption->OptCol++;\r
+ }\r
+ }\r
+ \r
+ for (Count = 0; OptionString[Index] != CHAR_NULL; Index++) {\r
+ OptionString[Count] = OptionString[Index];\r
+ Count++;\r
+ }\r
+ OptionString[Count] = CHAR_NULL;\r
+ \r
+ //\r
+ // Enable to suppress field in the opcode base on the flag.\r
+ //\r
+ if (Statement->OpCode->OpCode == EFI_IFR_DATE_OP) {\r
+ //\r
+ // OptionString format is: <**: **: ****>\r
+ // |month|day|year|\r
+ // 4 3 5\r
+ //\r
+ if ((Date->Flags & EFI_QF_DATE_MONTH_SUPPRESS) && (MenuOption->Sequence == 0)) {\r
+ //\r
+ // At this point, only "<**:" in the optionstring. \r
+ // Clean the day's ** field, after clean, the format is "< :"\r
+ //\r
+ SetUnicodeMem (&OptionString[1], 2, L' ');\r
+ } else if ((Date->Flags & EFI_QF_DATE_DAY_SUPPRESS) && (MenuOption->Sequence == 1)) {\r
+ //\r
+ // At this point, only "**:" in the optionstring. \r
+ // Clean the month's "**" field, after clean, the format is " :"\r
+ // \r
+ SetUnicodeMem (&OptionString[0], 2, L' ');\r
+ } else if ((Date->Flags & EFI_QF_DATE_YEAR_SUPPRESS) && (MenuOption->Sequence == 2)) {\r
+ //\r
+ // At this point, only "****>" in the optionstring. \r
+ // Clean the year's "****" field, after clean, the format is " >"\r
+ // \r
+ SetUnicodeMem (&OptionString[0], 4, L' ');\r
+ }\r
+ } else if (Statement->OpCode->OpCode == EFI_IFR_TIME_OP) {\r
+ //\r
+ // OptionString format is: <**: **: **>\r
+ // |hour|minute|second|\r
+ // 4 3 3\r
+ //\r
+ if ((Time->Flags & QF_TIME_HOUR_SUPPRESS) && (MenuOption->Sequence == 0)) {\r
+ //\r
+ // At this point, only "<**:" in the optionstring. \r
+ // Clean the hour's ** field, after clean, the format is "< :"\r
+ //\r
+ SetUnicodeMem (&OptionString[1], 2, L' ');\r
+ } else if ((Time->Flags & QF_TIME_MINUTE_SUPPRESS) && (MenuOption->Sequence == 1)) {\r
+ //\r
+ // At this point, only "**:" in the optionstring. \r
+ // Clean the minute's "**" field, after clean, the format is " :"\r
+ // \r
+ SetUnicodeMem (&OptionString[0], 2, L' ');\r
+ } else if ((Time->Flags & QF_TIME_SECOND_SUPPRESS) && (MenuOption->Sequence == 2)) {\r
+ //\r
+ // At this point, only "**>" in the optionstring. \r
+ // Clean the second's "**" field, after clean, the format is " >"\r
+ // \r
+ SetUnicodeMem (&OptionString[0], 2, L' ');\r
+ }\r
+ }\r
+}\r
+\r
+\r
+/**\r
+ Adjust Data and Time position accordingly.\r
+ Data format : [01/02/2004] [11:22:33]\r
+ Line number : 0 0 1 0 0 1\r
+\r
+ This is an internal function.\r
+\r
+ @param DirectionUp the up or down direction. False is down. True is\r
+ up.\r
+ @param CurrentPosition Current position. On return: Point to the last\r
+ Option (Year or Second) if up; Point to the first\r
+ Option (Month or Hour) if down.\r
+\r
+ @return Return line number to pad. It is possible that we stand on a zero-advance\r
+ @return data or time opcode, so pad one line when we judge if we are going to scroll outside.\r
+\r
+**/\r
+UINTN\r
+AdjustDateAndTimePosition (\r
+ IN BOOLEAN DirectionUp,\r
+ IN OUT LIST_ENTRY **CurrentPosition\r
+ )\r
+{\r
+ UINTN Count;\r
+ LIST_ENTRY *NewPosition;\r
+ UI_MENU_OPTION *MenuOption;\r
+ UINTN PadLineNumber;\r
+\r
+ PadLineNumber = 0;\r
+ NewPosition = *CurrentPosition;\r
+ MenuOption = MENU_OPTION_FROM_LINK (NewPosition);\r
+\r
+ if ((MenuOption->ThisTag->OpCode->OpCode == EFI_IFR_DATE_OP) ||\r
+ (MenuOption->ThisTag->OpCode->OpCode == EFI_IFR_TIME_OP)) {\r
+ //\r
+ // Calculate the distance from current position to the last Date/Time MenuOption\r
+ //\r
+ Count = 0;\r
+ while (MenuOption->Skip == 0) {\r
+ Count++;\r
+ NewPosition = NewPosition->ForwardLink;\r
+ MenuOption = MENU_OPTION_FROM_LINK (NewPosition);\r
+ PadLineNumber = 1;\r
+ }\r
+\r
+ NewPosition = *CurrentPosition;\r
+ if (DirectionUp) {\r
+ //\r
+ // Since the behavior of hitting the up arrow on a Date/Time MenuOption is intended\r
+ // to be one that back to the previous set of MenuOptions, we need to advance to the first\r
+ // Date/Time MenuOption and leave the remaining logic in CfUiUp intact so the appropriate\r
+ // checking can be done.\r
+ //\r
+ while (Count++ < 2) {\r
+ NewPosition = NewPosition->BackLink;\r
+ }\r
+ } else {\r
+ //\r
+ // Since the behavior of hitting the down arrow on a Date/Time MenuOption is intended\r
+ // to be one that progresses to the next set of MenuOptions, we need to advance to the last\r
+ // Date/Time MenuOption and leave the remaining logic in CfUiDown intact so the appropriate\r
+ // checking can be done.\r
+ //\r
+ while (Count-- > 0) {\r
+ NewPosition = NewPosition->ForwardLink;\r
+ }\r
+ }\r
+\r
+ *CurrentPosition = NewPosition;\r
+ }\r
+\r
+ return PadLineNumber;\r
+}\r
+\r
+/**\r
+ Get step info from numeric opcode.\r
+ \r
+ @param[in] OpCode The input numeric op code.\r
+\r
+ @return step info for this opcode.\r
+**/\r
+UINT64\r
+GetFieldFromNum (\r
+ IN EFI_IFR_OP_HEADER *OpCode\r
+ )\r
+{\r
+ EFI_IFR_NUMERIC *NumericOp;\r
+ UINT64 Step;\r
+\r
+ NumericOp = (EFI_IFR_NUMERIC *) OpCode;\r
+ \r
+ switch (NumericOp->Flags & EFI_IFR_NUMERIC_SIZE) {\r
+ case EFI_IFR_NUMERIC_SIZE_1:\r
+ Step = NumericOp->data.u8.Step;\r
+ break;\r
+ \r
+ case EFI_IFR_NUMERIC_SIZE_2:\r
+ Step = NumericOp->data.u16.Step;\r
+ break;\r
+ \r
+ case EFI_IFR_NUMERIC_SIZE_4:\r
+ Step = NumericOp->data.u32.Step;\r
+ break;\r
+ \r
+ case EFI_IFR_NUMERIC_SIZE_8:\r
+ Step = NumericOp->data.u64.Step;\r
+ break;\r
+ \r
+ default:\r
+ Step = 0;\r
+ break;\r
+ }\r
+\r
+ return Step;\r
+}\r
+\r
+/**\r
+ Find the registered HotKey based on KeyData.\r
+ \r
+ @param[in] KeyData A pointer to a buffer that describes the keystroke\r
+ information for the hot key.\r
+\r
+ @return The registered HotKey context. If no found, NULL will return.\r
+**/\r
+BROWSER_HOT_KEY *\r
+GetHotKeyFromRegisterList (\r
+ IN EFI_INPUT_KEY *KeyData\r
+ )\r
+{\r
+ LIST_ENTRY *Link;\r
+ BROWSER_HOT_KEY *HotKey;\r
+\r
+ Link = GetFirstNode (&gFormData->HotKeyListHead);\r
+ while (!IsNull (&gFormData->HotKeyListHead, Link)) {\r
+ HotKey = BROWSER_HOT_KEY_FROM_LINK (Link);\r
+ \r
+ if (HotKey->KeyData->ScanCode == KeyData->ScanCode) {\r
+ return HotKey;\r
+ }\r
+\r
+ Link = GetNextNode (&gFormData->HotKeyListHead, Link);\r
+ }\r
+ \r
+ return NULL;\r
+}\r
+\r
+\r
+/**\r
+ Determine if the menu is the last menu that can be selected.\r
+\r
+ This is an internal function.\r
+\r
+ @param Direction The scroll direction. False is down. True is up.\r
+ @param CurrentPos The current focus.\r
+\r
+ @return FALSE -- the menu isn't the last menu that can be selected.\r
+ @return TRUE -- the menu is the last menu that can be selected.\r
+\r
+**/\r
+BOOLEAN\r
+ValueIsScroll (\r
+ IN BOOLEAN Direction,\r
+ IN LIST_ENTRY *CurrentPos\r
+ )\r
+{\r
+ LIST_ENTRY *Temp;\r
+\r
+ Temp = Direction ? CurrentPos->BackLink : CurrentPos->ForwardLink;\r
+\r
+ if (Temp == &gMenuOption) {\r
+ return TRUE;\r
+ }\r
+\r
+ return FALSE;\r
+}\r
+\r
+/**\r
+ Wait for a given event to fire, or for an optional timeout to expire.\r
+\r
+ @param Event The event to wait for\r
+\r
+ @retval UI_EVENT_TYPE The type of the event which is trigged.\r
+\r
+**/\r
+UI_EVENT_TYPE\r
+UiWaitForEvent (\r
+ IN EFI_EVENT Event\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ UINTN Index;\r
+ UINTN EventNum;\r
+ UINT64 Timeout;\r
+ EFI_EVENT TimerEvent;\r
+ EFI_EVENT WaitList[3];\r
+ UI_EVENT_TYPE EventType;\r
+\r
+ TimerEvent = NULL;\r
+ Timeout = FormExitTimeout(gFormData);\r
+\r
+ if (Timeout != 0) {\r
+ Status = gBS->CreateEvent (EVT_TIMER, 0, NULL, NULL, &TimerEvent);\r
+\r
+ //\r
+ // Set the timer event\r
+ //\r
+ gBS->SetTimer (\r
+ TimerEvent,\r
+ TimerRelative,\r
+ Timeout\r
+ );\r
+ }\r
+ \r
+ WaitList[0] = Event;\r
+ EventNum = 1;\r
+ if (gFormData->FormRefreshEvent != NULL) {\r
+ WaitList[EventNum] = gFormData->FormRefreshEvent;\r
+ EventNum ++;\r
+ } \r
+\r
+ if (Timeout != 0) {\r
+ WaitList[EventNum] = TimerEvent;\r
+ EventNum ++;\r
+ }\r
+\r
+ Status = gBS->WaitForEvent (EventNum, WaitList, &Index);\r
+ ASSERT_EFI_ERROR (Status);\r
+\r
+ switch (Index) {\r
+ case 0:\r
+ EventType = UIEventKey;\r
+ break;\r
+\r
+ case 1:\r
+ if (gFormData->FormRefreshEvent != NULL) {\r
+ EventType = UIEventDriver;\r
+ } else {\r
+ ASSERT (Timeout != 0 && EventNum == 2);\r
+ EventType = UIEventTimeOut;\r
+ }\r
+ break;\r
+\r
+ default:\r
+ ASSERT (Index == 2 && EventNum == 3);\r
+ EventType = UIEventTimeOut;\r
+ break;\r
+ }\r
+\r
+ if (Timeout != 0) {\r
+ gBS->CloseEvent (TimerEvent);\r
+ }\r
+ \r
+ return EventType;\r
+}\r
+\r
+/**\r
+ Get question id info from the input opcode header.\r
+\r
+ @param OpCode The input opcode header pointer.\r
+\r
+ @retval The question id for this opcode.\r
+\r
+**/\r
+EFI_QUESTION_ID\r
+GetQuestionIdInfo (\r
+ IN EFI_IFR_OP_HEADER *OpCode\r
+ )\r
+{\r
+ EFI_IFR_QUESTION_HEADER *QuestionHeader;\r
+\r
+ if (OpCode->Length < sizeof (EFI_IFR_OP_HEADER) + sizeof (EFI_IFR_QUESTION_HEADER)) {\r
+ return 0;\r
+ }\r
+\r
+ QuestionHeader = (EFI_IFR_QUESTION_HEADER *)((UINT8 *) OpCode + sizeof(EFI_IFR_OP_HEADER));\r
+\r
+ return QuestionHeader->QuestionId;\r
+}\r
+\r
+/**\r
+ Find the first menu which will be show at the top.\r
+\r
+ @param FormData The data info for this form.\r
+ @param TopOfScreen The link_entry pointer to top menu.\r
+ @param HighlightMenu The menu which will be highlight.\r
+ @param SkipValue The skip value for the top menu.\r
+\r
+**/\r
+VOID\r
+FindTopMenu (\r
+ IN FORM_DISPLAY_ENGINE_FORM *FormData,\r
+ OUT LIST_ENTRY **TopOfScreen,\r
+ OUT LIST_ENTRY **HighlightMenu,\r
+ OUT INTN *SkipValue\r
+ )\r
+{\r
+ LIST_ENTRY *Link;\r
+ LIST_ENTRY *NewPos;\r
+ UINTN TopRow;\r
+ UINTN BottomRow;\r
+ UINTN Index;\r
+ UI_MENU_OPTION *SavedMenuOption;\r
+ UINTN EndRow;\r
+\r
+ TopRow = gStatementDimensions.TopRow + SCROLL_ARROW_HEIGHT;\r
+ BottomRow = gStatementDimensions.BottomRow - SCROLL_ARROW_HEIGHT;\r
+\r
+ //\r
+ // If not has input highlight statement, just return the first one in this form.\r
+ //\r
+ if (FormData->HighLightedStatement == NULL) {\r
+ *TopOfScreen = gMenuOption.ForwardLink;\r
+ *HighlightMenu = gMenuOption.ForwardLink;\r
+ if (!IsListEmpty (&gMenuOption)) {\r
+ MoveToNextStatement (FALSE, HighlightMenu, BottomRow - TopRow);\r
+ }\r
+ *SkipValue = 0;\r
+ return;\r
+ }\r
+\r
+ //\r
+ // Now base on the input highlight menu to find the top menu in this page.\r
+ // Will base on the highlight menu show at the bottom to find the top menu.\r
+ //\r
+ NewPos = gMenuOption.ForwardLink;\r
+ SavedMenuOption = MENU_OPTION_FROM_LINK (NewPos);\r
+\r
+ while ((SavedMenuOption->ThisTag != FormData->HighLightedStatement) ||\r
+ (SavedMenuOption->Sequence != gSequence)) {\r
+ NewPos = NewPos->ForwardLink;\r
+ if (NewPos == &gMenuOption) {\r
+ //\r
+ // Not Found it, break\r
+ //\r
+ break;\r
+ }\r
+ SavedMenuOption = MENU_OPTION_FROM_LINK (NewPos);\r
+ }\r
+ ASSERT (SavedMenuOption->ThisTag == FormData->HighLightedStatement);\r
+\r
+ *HighlightMenu = NewPos;\r
+\r
+ AdjustDateAndTimePosition(FALSE, &NewPos);\r
+ SavedMenuOption = MENU_OPTION_FROM_LINK (NewPos);\r
+ UpdateOptionSkipLines (SavedMenuOption);\r
+\r
+ //\r
+ // If highlight opcode is date/time, keep the highlight row info not change.\r
+ //\r
+ if ((SavedMenuOption->ThisTag->OpCode->OpCode == EFI_IFR_DATE_OP || SavedMenuOption->ThisTag->OpCode->OpCode == EFI_IFR_TIME_OP) &&\r
+ (gHighligthMenuInfo.QuestionId != 0) && \r
+ (gHighligthMenuInfo.QuestionId == GetQuestionIdInfo(SavedMenuOption->ThisTag->OpCode))) {\r
+ //\r
+ // Still show the highlight menu before exit from display engine.\r
+ //\r
+ EndRow = gHighligthMenuInfo.DisplayRow + SavedMenuOption->Skip;\r
+ } else {\r
+ EndRow = BottomRow;\r
+ }\r
+\r
+ //\r
+ // Base on the selected menu will show at the bottome of next page, \r
+ // select the menu show at the top of the next page. \r
+ //\r
+ Link = NewPos;\r
+ for (Index = TopRow + SavedMenuOption->Skip; Index <= EndRow; ) {\r
+ Link = Link->BackLink;\r
+ //\r
+ // Already find the first menu in this form, means highlight menu \r
+ // will show in first page of this form.\r
+ //\r
+ if (Link == &gMenuOption) {\r
+ *TopOfScreen = gMenuOption.ForwardLink;\r
+ *SkipValue = 0;\r
+ return;\r
+ }\r
+ SavedMenuOption = MENU_OPTION_FROM_LINK (Link);\r
+ UpdateOptionSkipLines (SavedMenuOption);\r
+ Index += SavedMenuOption->Skip;\r
+ }\r
+\r
+ //\r
+ // Found the menu which will show at the top of the page.\r
+ //\r
+ if (Link == NewPos) {\r
+ //\r
+ // The menu can show more than one pages, just show the menu at the top of the page.\r
+ //\r
+ *SkipValue = 0;\r
+ *TopOfScreen = Link;\r
+ } else {\r
+ //\r
+ // Check whether need to skip some line for menu shows at the top of the page.\r
+ //\r
+ *SkipValue = Index - EndRow;\r
+ if (*SkipValue > 0 && *SkipValue < (INTN) SavedMenuOption->Skip) {\r
+ *TopOfScreen = Link;\r
+ } else {\r
+ *SkipValue = 0;\r
+ *TopOfScreen = Link->ForwardLink;\r
+ }\r
+ }\r
+}\r
+\r
+/**\r
+ Display menu and wait for user to select one menu option, then return it.\r
+ If AutoBoot is enabled, then if user doesn't select any option,\r
+ after period of time, it will automatically return the first menu option.\r
+\r
+ @param FormData The current form data info.\r
+\r
+ @retval EFI_SUCESSS Process the user selection success.\r
+ @retval EFI_NOT_FOUND Process option string for orderedlist/Oneof fail.\r
+\r
+**/\r
+EFI_STATUS\r
+UiDisplayMenu (\r
+ IN FORM_DISPLAY_ENGINE_FORM *FormData\r
+ )\r
+{\r
+ INTN SkipValue;\r
+ INTN Difference;\r
+ UINTN DistanceValue;\r
+ UINTN Row;\r
+ UINTN Col;\r
+ UINTN TempRightCol;\r
+ UINTN Temp;\r
+ UINTN Temp2;\r
+ UINTN Temp3;\r
+ UINTN TopRow;\r
+ UINTN BottomRow;\r
+ UINTN OriginalRow;\r
+ UINTN Index;\r
+ UINT16 Width;\r
+ CHAR16 *StringPtr;\r
+ CHAR16 *OptionString;\r
+ CHAR16 *OutputString;\r
+ CHAR16 *HelpString;\r
+ CHAR16 *HelpHeaderString;\r
+ CHAR16 *HelpBottomString;\r
+ BOOLEAN NewLine;\r
+ BOOLEAN Repaint;\r
+ BOOLEAN UpArrow;\r
+ BOOLEAN DownArrow;\r
+ EFI_STATUS Status;\r
+ EFI_INPUT_KEY Key;\r
+ LIST_ENTRY *Link;\r
+ LIST_ENTRY *NewPos;\r
+ LIST_ENTRY *TopOfScreen;\r
+ LIST_ENTRY *SavedListEntry;\r
+ UI_MENU_OPTION *MenuOption;\r
+ UI_MENU_OPTION *NextMenuOption;\r
+ UI_MENU_OPTION *SavedMenuOption;\r
+ UI_MENU_OPTION *PreviousMenuOption;\r
+ UI_CONTROL_FLAG ControlFlag;\r
+ UI_SCREEN_OPERATION ScreenOperation;\r
+ UINT16 DefaultId;\r
+ FORM_DISPLAY_ENGINE_STATEMENT *Statement;\r
+ UINTN ModalSkipColumn;\r
+ BROWSER_HOT_KEY *HotKey;\r
+ UINTN HelpPageIndex;\r
+ UINTN HelpPageCount;\r
+ UINTN RowCount;\r
+ UINTN HelpLine;\r
+ UINTN HelpHeaderLine;\r
+ UINTN HelpBottomLine;\r
+ BOOLEAN MultiHelpPage;\r
+ UINT16 GlyphWidth;\r
+ UINT16 EachLineWidth;\r
+ UINT16 HeaderLineWidth;\r
+ UINT16 BottomLineWidth;\r
+ EFI_STRING_ID HelpInfo;\r
+ UI_EVENT_TYPE EventType;\r
+ FORM_DISPLAY_ENGINE_STATEMENT *InitialHighlight;\r
+\r
+ EventType = UIEventNone;\r
+ Status = EFI_SUCCESS;\r
+ HelpString = NULL;\r
+ HelpHeaderString = NULL;\r
+ HelpBottomString = NULL;\r
+ OptionString = NULL;\r
+ ScreenOperation = UiNoOperation;\r
+ NewLine = TRUE;\r
+ DefaultId = 0;\r
+ HelpPageCount = 0;\r
+ HelpLine = 0;\r
+ RowCount = 0;\r
+ HelpBottomLine = 0;\r
+ HelpHeaderLine = 0;\r
+ HelpPageIndex = 0;\r
+ MultiHelpPage = FALSE;\r
+ EachLineWidth = 0;\r
+ HeaderLineWidth = 0;\r
+ BottomLineWidth = 0;\r
+ OutputString = NULL;\r
+ UpArrow = FALSE;\r
+ DownArrow = FALSE;\r
+ SkipValue = 0;\r
+\r
+ NextMenuOption = NULL;\r
+ PreviousMenuOption = NULL;\r
+ SavedMenuOption = NULL;\r
+ HotKey = NULL;\r
+ Repaint = TRUE;\r
+ MenuOption = NULL;\r
+ ModalSkipColumn = (gStatementDimensions.RightColumn - gStatementDimensions.LeftColumn) / 6;\r
+ InitialHighlight = gFormData->HighLightedStatement;\r
+\r
+ ZeroMem (&Key, sizeof (EFI_INPUT_KEY));\r
+\r
+ gOptionBlockWidth = (CHAR16) ((gStatementDimensions.RightColumn - gStatementDimensions.LeftColumn) / 3);\r
+ gPromptBlockWidth = (CHAR16) (gOptionBlockWidth + LEFT_SKIPPED_COLUMNS);\r
+ gHelpBlockWidth = (CHAR16) (gOptionBlockWidth - LEFT_SKIPPED_COLUMNS);\r
+\r
+ TopRow = gStatementDimensions.TopRow + SCROLL_ARROW_HEIGHT;\r
+ BottomRow = gStatementDimensions.BottomRow - SCROLL_ARROW_HEIGHT - 1;\r
+\r
+ Row = TopRow;\r
+ if ((FormData->Attribute & HII_DISPLAY_MODAL) != 0) {\r
+ Col = gStatementDimensions.LeftColumn + LEFT_SKIPPED_COLUMNS + ModalSkipColumn;\r
+ } else {\r
+ Col = gStatementDimensions.LeftColumn + LEFT_SKIPPED_COLUMNS;\r
+ }\r
+\r
+ FindTopMenu(FormData, &TopOfScreen, &NewPos, &SkipValue);\r
+\r
+ gST->ConOut->EnableCursor (gST->ConOut, FALSE);\r
+\r
+ ControlFlag = CfInitialization;\r
+ while (TRUE) {\r
+ switch (ControlFlag) {\r
+ case CfInitialization:\r
+ if (IsListEmpty (&gMenuOption)) {\r
+ \r
+ if ((FormData->Attribute & HII_DISPLAY_MODAL) == 0) {\r
+ //\r
+ // Clear Statement range.\r
+ //\r
+ ClearLines (\r
+ gStatementDimensions.LeftColumn,\r
+ gStatementDimensions.RightColumn,\r
+ TopRow - SCROLL_ARROW_HEIGHT,\r
+ BottomRow + SCROLL_ARROW_HEIGHT,\r
+ GetFieldTextColor ()\r
+ );\r
+ \r
+ //\r
+ // Clear Key Range\r
+ //\r
+ RefreshKeyHelp (gFormData, NULL, FALSE);\r
+ }\r
+\r
+ ControlFlag = CfReadKey;\r
+ } else {\r
+ ControlFlag = CfRepaint;\r
+ }\r
+ break;\r
+\r
+ case CfRepaint:\r
+ ControlFlag = CfRefreshHighLight;\r
+\r
+ if (Repaint) {\r
+ //\r
+ // Display menu\r
+ //\r
+ DownArrow = FALSE;\r
+ UpArrow = FALSE;\r
+ Row = TopRow;\r
+\r
+ Temp = (UINTN) SkipValue;\r
+ Temp2 = (UINTN) SkipValue;\r
+ Temp3 = (UINTN) SkipValue;\r
+\r
+ //\r
+ // 1. Clear the screen.\r
+ //\r
+ if ((FormData->Attribute & HII_DISPLAY_MODAL) != 0) {\r
+ ClearLines (\r
+ gStatementDimensions.LeftColumn + ModalSkipColumn,\r
+ gStatementDimensions.LeftColumn + ModalSkipColumn + gPromptBlockWidth + gOptionBlockWidth,\r
+ TopRow - SCROLL_ARROW_HEIGHT,\r
+ BottomRow + SCROLL_ARROW_HEIGHT,\r
+ GetFieldTextColor ()\r
+ );\r
+ } else {\r
+ TempRightCol = gStatementDimensions.RightColumn;\r
+ if (!mStatementLayoutIsChanged) {\r
+ TempRightCol = gStatementDimensions.RightColumn - gHelpBlockWidth;\r
+ }\r
+ ClearLines (\r
+ gStatementDimensions.LeftColumn,\r
+ gStatementDimensions.RightColumn,\r
+ TopRow - SCROLL_ARROW_HEIGHT,\r
+ TopRow - 1,\r
+ GetFieldTextColor ()\r
+ );\r
+ ClearLines (\r
+ gStatementDimensions.LeftColumn,\r
+ TempRightCol,\r
+ TopRow,\r
+ BottomRow,\r
+ GetFieldTextColor ()\r
+ );\r
+ ClearLines (\r
+ gStatementDimensions.LeftColumn,\r
+ gStatementDimensions.RightColumn,\r
+ BottomRow + 1,\r
+ BottomRow + SCROLL_ARROW_HEIGHT,\r
+ GetFieldTextColor ()\r
+ );\r
+ }\r
+\r
+ //\r
+ // 2.Paint the menu.\r
+ //\r
+ for (Link = TopOfScreen; Link != &gMenuOption; Link = Link->ForwardLink) {\r
+ MenuOption = MENU_OPTION_FROM_LINK (Link);\r
+ MenuOption->Row = Row;\r
+ MenuOption->Col = Col;\r
+ if ((FormData->Attribute & HII_DISPLAY_MODAL) != 0) {\r
+ MenuOption->OptCol = gPromptBlockWidth + 1 + gStatementDimensions.LeftColumn + ModalSkipColumn;\r
+ } else {\r
+ MenuOption->OptCol = gPromptBlockWidth + 1 + gStatementDimensions.LeftColumn;\r
+ }\r
+\r
+ Statement = MenuOption->ThisTag;\r
+ if (MenuOption->NestInStatement) {\r
+ MenuOption->Col += SUBTITLE_INDENT;\r
+ }\r
+\r
+ if (MenuOption->GrayOut) {\r
+ gST->ConOut->SetAttribute (gST->ConOut, GetGrayedTextColor ());\r
+ } else {\r
+ if (Statement->OpCode->OpCode == EFI_IFR_SUBTITLE_OP) {\r
+ gST->ConOut->SetAttribute (gST->ConOut, GetSubTitleTextColor ());\r
+ }\r
+ }\r
+\r
+ Width = GetWidth (Statement);\r
+ OriginalRow = Row;\r
+ GlyphWidth = 1;\r
+\r
+ if (Statement->OpCode->OpCode == EFI_IFR_REF_OP && MenuOption->Col >= 2) {\r
+ //\r
+ // Print Arrow for Goto button.\r
+ //\r
+ PrintCharAt (\r
+ MenuOption->Col - 2,\r
+ Row,\r
+ GEOMETRICSHAPE_RIGHT_TRIANGLE\r
+ );\r
+ }\r
+\r
+ //\r
+ // 2.1. Paint the description.\r
+ //\r
+ for (Index = 0; GetLineByWidth (MenuOption->Description, Width, &GlyphWidth, &Index, &OutputString) != 0x0000;) {\r
+ //\r
+ // Temp means need to skip how many lines from the start.\r
+ //\r
+ if ((Temp == 0) && (Row <= BottomRow)) {\r
+ PrintStringAt (MenuOption->Col, Row, OutputString);\r
+ }\r
+ //\r
+ // If there is more string to process print on the next row and increment the Skip value\r
+ //\r
+ if (StrLen (&MenuOption->Description[Index]) != 0) {\r
+ if (Temp == 0) {\r
+ Row++;\r
+ }\r
+ }\r
+\r
+ FreePool (OutputString);\r
+ if (Temp != 0) {\r
+ Temp--;\r
+ }\r
+ }\r
+\r
+ Temp = 0;\r
+ Row = OriginalRow;\r
+\r
+ //\r
+ // 2.2. Paint the option string.\r
+ //\r
+ Status = ProcessOptions (MenuOption, FALSE, &OptionString, FALSE);\r
+ //\r
+ // If Error occur, question value update in ProcessOptions.\r
+ // Exit current FormDisplay with new question value.\r
+ //\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ if (OptionString != NULL) {\r
+ if (Statement->OpCode->OpCode == EFI_IFR_DATE_OP || Statement->OpCode->OpCode == EFI_IFR_TIME_OP) {\r
+ ProcessStringForDateTime(MenuOption, OptionString, TRUE);\r
+ }\r
+\r
+ Width = (UINT16) gOptionBlockWidth;\r
+ OriginalRow = Row;\r
+ GlyphWidth = 1;\r
+\r
+ for (Index = 0; GetLineByWidth (OptionString, Width, &GlyphWidth, &Index, &OutputString) != 0x0000;) {\r
+ if ((Temp2 == 0) && (Row <= BottomRow)) {\r
+ PrintStringAt (MenuOption->OptCol, Row, OutputString);\r
+ }\r
+ //\r
+ // If there is more string to process print on the next row and increment the Skip value\r
+ //\r
+ if (StrLen (&OptionString[Index]) != 0) {\r
+ if (Temp2 == 0) {\r
+ Row++;\r
+ //\r
+ // Since the Number of lines for this menu entry may or may not be reflected accurately\r
+ // since the prompt might be 1 lines and option might be many, and vice versa, we need to do\r
+ // some testing to ensure we are keeping this in-sync.\r
+ //\r
+ // If the difference in rows is greater than or equal to the skip value, increase the skip value\r
+ //\r
+ if ((Row - OriginalRow) >= MenuOption->Skip) {\r
+ MenuOption->Skip++;\r
+ }\r
+ }\r
+ }\r
+\r
+ FreePool (OutputString);\r
+ if (Temp2 != 0) {\r
+ Temp2--;\r
+ }\r
+ }\r
+\r
+ Row = OriginalRow;\r
+\r
+ FreePool (OptionString);\r
+ }\r
+ Temp2 = 0;\r
+\r
+ //\r
+ // If this is a text op with secondary text information\r
+ //\r
+ if ((Statement->OpCode->OpCode == EFI_IFR_TEXT_OP) && (((EFI_IFR_TEXT*)Statement->OpCode)->TextTwo != 0)) {\r
+ StringPtr = GetToken (((EFI_IFR_TEXT*)Statement->OpCode)->TextTwo, gFormData->HiiHandle);\r
+\r
+ Width = (UINT16) gOptionBlockWidth;\r
+ OriginalRow = Row;\r
+ GlyphWidth = 1;\r
+\r
+ for (Index = 0; GetLineByWidth (StringPtr, Width, &GlyphWidth, &Index, &OutputString) != 0x0000;) {\r
+ if ((Temp3 == 0) && (Row <= BottomRow)) {\r
+ PrintStringAt (MenuOption->OptCol, Row, OutputString);\r
+ }\r
+ //\r
+ // If there is more string to process print on the next row and increment the Skip value\r
+ //\r
+ if (StrLen (&StringPtr[Index]) != 0) {\r
+ if (Temp3 == 0) {\r
+ Row++;\r
+ //\r
+ // Since the Number of lines for this menu entry may or may not be reflected accurately\r
+ // since the prompt might be 1 lines and option might be many, and vice versa, we need to do\r
+ // some testing to ensure we are keeping this in-sync.\r
+ //\r
+ // If the difference in rows is greater than or equal to the skip value, increase the skip value\r
+ //\r
+ if ((Row - OriginalRow) >= MenuOption->Skip) {\r
+ MenuOption->Skip++;\r
+ }\r
+ }\r
+ }\r
+\r
+ FreePool (OutputString);\r
+ if (Temp3 != 0) {\r
+ Temp3--;\r
+ }\r
+ }\r
+\r
+ Row = OriginalRow;\r
+ FreePool (StringPtr);\r
+ }\r
+ Temp3 = 0;\r
+\r
+ gST->ConOut->SetAttribute (gST->ConOut, GetFieldTextColor ());\r
+\r
+ //\r
+ // 3. Update the row info which will be used by next menu.\r
+ //\r
+ if (Link == TopOfScreen) {\r
+ Row += MenuOption->Skip - SkipValue;\r
+ } else {\r
+ Row += MenuOption->Skip;\r
+ }\r
+\r
+ if (Row > BottomRow) {\r
+ if (!ValueIsScroll (FALSE, Link)) {\r
+ DownArrow = TRUE;\r
+ }\r
+\r
+ Row = BottomRow + 1;\r
+ break;\r
+ }\r
+ }\r
+\r
+ if (!ValueIsScroll (TRUE, TopOfScreen)) {\r
+ UpArrow = TRUE;\r
+ }\r
+\r
+ if (UpArrow) {\r
+ gST->ConOut->SetAttribute (gST->ConOut, GetArrowColor ());\r
+ PrintCharAt (\r
+ gStatementDimensions.LeftColumn + gPromptBlockWidth + gOptionBlockWidth + 1,\r
+ TopRow - SCROLL_ARROW_HEIGHT,\r
+ ARROW_UP\r
+ );\r
+ gST->ConOut->SetAttribute (gST->ConOut, GetFieldTextColor ());\r
+ }\r
+\r
+ if (DownArrow) {\r
+ gST->ConOut->SetAttribute (gST->ConOut, GetArrowColor ());\r
+ PrintCharAt (\r
+ gStatementDimensions.LeftColumn + gPromptBlockWidth + gOptionBlockWidth + 1,\r
+ BottomRow + SCROLL_ARROW_HEIGHT,\r
+ ARROW_DOWN\r
+ );\r
+ gST->ConOut->SetAttribute (gST->ConOut, GetFieldTextColor ());\r
+ }\r
+\r
+ MenuOption = NULL;\r
+ }\r
+ break;\r
+\r
+ case CfRefreshHighLight:\r
+\r
+ //\r
+ // MenuOption: Last menu option that need to remove hilight\r
+ // MenuOption is set to NULL in Repaint\r
+ // NewPos: Current menu option that need to hilight\r
+ //\r
+ ControlFlag = CfUpdateHelpString;\r
+\r
+ if (MenuOption != NULL && TopOfScreen == &MenuOption->Link) {\r
+ Temp = SkipValue;\r
+ } else {\r
+ Temp = 0;\r
+ }\r
+ if (NewPos == TopOfScreen) {\r
+ Temp2 = SkipValue;\r
+ } else {\r
+ Temp2 = 0;\r
+ }\r
+\r
+ if (NewPos != NULL && (MenuOption == NULL || NewPos != &MenuOption->Link)) {\r
+ if (MenuOption != NULL) {\r
+ //\r
+ // Remove highlight on last Menu Option\r
+ //\r
+ gST->ConOut->SetCursorPosition (gST->ConOut, MenuOption->Col, MenuOption->Row);\r
+ ProcessOptions (MenuOption, FALSE, &OptionString, TRUE);\r
+ gST->ConOut->SetAttribute (gST->ConOut, GetFieldTextColor ());\r
+ if (OptionString != NULL) {\r
+ if ((MenuOption->ThisTag->OpCode->OpCode == EFI_IFR_DATE_OP) ||\r
+ (MenuOption->ThisTag->OpCode->OpCode == EFI_IFR_TIME_OP)\r
+ ) {\r
+ ProcessStringForDateTime(MenuOption, OptionString, FALSE);\r
+ }\r
+\r
+ Width = (UINT16) gOptionBlockWidth;\r
+ OriginalRow = MenuOption->Row;\r
+ GlyphWidth = 1;\r
+\r
+ for (Index = 0; GetLineByWidth (OptionString, Width, &GlyphWidth, &Index, &OutputString) != 0x0000;) {\r
+ if ((Temp == 0) && (MenuOption->Row >= TopRow) && (MenuOption->Row <= BottomRow)) {\r
+ PrintStringAt (MenuOption->OptCol, MenuOption->Row, OutputString);\r
+ }\r
+ //\r
+ // If there is more string to process print on the next row and increment the Skip value\r
+ //\r
+ if (StrLen (&OptionString[Index]) != 0) {\r
+ if (Temp == 0) {\r
+ MenuOption->Row++;\r
+ }\r
+ }\r
+\r
+ FreePool (OutputString);\r
+ if (Temp != 0) {\r
+ Temp--;\r
+ }\r
+ }\r
+\r
+ MenuOption->Row = OriginalRow;\r
+\r
+ FreePool (OptionString);\r
+ } else {\r
+ if (NewLine) {\r
+ if (MenuOption->GrayOut) {\r
+ gST->ConOut->SetAttribute (gST->ConOut, GetGrayedTextColor ());\r
+ } else if (MenuOption->ThisTag->OpCode->OpCode == EFI_IFR_SUBTITLE_OP) {\r
+ gST->ConOut->SetAttribute (gST->ConOut, GetSubTitleTextColor ());\r
+ }\r
+\r
+ OriginalRow = MenuOption->Row;\r
+ Width = GetWidth (MenuOption->ThisTag);\r
+ GlyphWidth = 1;\r
+\r
+ for (Index = 0; GetLineByWidth (MenuOption->Description, Width, &GlyphWidth, &Index, &OutputString) != 0x0000;) {\r
+ if ((Temp == 0) && (MenuOption->Row >= TopRow) && (MenuOption->Row <= BottomRow)) {\r
+ PrintStringAt (MenuOption->Col, MenuOption->Row, OutputString);\r
+ }\r
+ //\r
+ // If there is more string to process print on the next row and increment the Skip value\r
+ //\r
+ if (StrLen (&MenuOption->Description[Index]) != 0) {\r
+ if (Temp == 0) {\r
+ MenuOption->Row++;\r
+ }\r
+ }\r
+\r
+ FreePool (OutputString);\r
+ if (Temp != 0) {\r
+ Temp--;\r
+ }\r
+ }\r
+\r
+ MenuOption->Row = OriginalRow;\r
+ gST->ConOut->SetAttribute (gST->ConOut, GetFieldTextColor ());\r
+ }\r
+ }\r
+ }\r
+\r
+ //\r
+ // This is the current selected statement\r
+ //\r
+ MenuOption = MENU_OPTION_FROM_LINK (NewPos);\r
+ Statement = MenuOption->ThisTag;\r
+\r
+ //\r
+ // Get the highlight statement.\r
+ //\r
+ gUserInput->SelectedStatement = Statement;\r
+ gSequence = (UINT16) MenuOption->Sequence;\r
+\r
+ //\r
+ // Record highlight row info for date/time opcode.\r
+ //\r
+ if (Statement->OpCode->OpCode == EFI_IFR_DATE_OP || Statement->OpCode->OpCode == EFI_IFR_TIME_OP) {\r
+ gHighligthMenuInfo.QuestionId = GetQuestionIdInfo(Statement->OpCode);\r
+ gHighligthMenuInfo.DisplayRow = (UINT16) MenuOption->Row;\r
+ } else {\r
+ gHighligthMenuInfo.QuestionId = 0;\r
+ gHighligthMenuInfo.DisplayRow = 0;\r
+ }\r
+\r
+ if (!IsSelectable (MenuOption)) {\r
+ RefreshKeyHelp(gFormData, Statement, FALSE);\r
+ break;\r
+ }\r
+\r
+ //\r
+ // Set reverse attribute\r
+ //\r
+ gST->ConOut->SetAttribute (gST->ConOut, GetHighlightTextColor ());\r
+ gST->ConOut->SetCursorPosition (gST->ConOut, MenuOption->Col, MenuOption->Row);\r
+\r
+ ProcessOptions (MenuOption, FALSE, &OptionString, TRUE);\r
+ if (OptionString != NULL) {\r
+ if (Statement->OpCode->OpCode == EFI_IFR_DATE_OP || Statement->OpCode->OpCode == EFI_IFR_TIME_OP) {\r
+ ProcessStringForDateTime(MenuOption, OptionString, FALSE);\r
+ }\r
+ Width = (UINT16) gOptionBlockWidth;\r
+\r
+ OriginalRow = MenuOption->Row;\r
+ GlyphWidth = 1;\r
+\r
+ for (Index = 0; GetLineByWidth (OptionString, Width, &GlyphWidth, &Index, &OutputString) != 0x0000;) {\r
+ if ((Temp2 == 0) && (MenuOption->Row >= TopRow) && (MenuOption->Row <= BottomRow) ) {\r
+ PrintStringAt (MenuOption->OptCol, MenuOption->Row, OutputString);\r
+ }\r
+ //\r
+ // If there is more string to process print on the next row and increment the Skip value\r
+ //\r
+ if (StrLen (&OptionString[Index]) != 0) {\r
+ if (Temp2 == 0) {\r
+ MenuOption->Row++;\r
+ }\r
+ }\r
+\r
+ FreePool (OutputString);\r
+ if (Temp2 != 0) {\r
+ Temp2--;\r
+ }\r
+ }\r
+\r
+ MenuOption->Row = OriginalRow;\r
+\r
+ FreePool (OptionString);\r
+ } else {\r
+ if (NewLine) {\r
+ OriginalRow = MenuOption->Row;\r
+\r
+ Width = GetWidth (Statement);\r
+ GlyphWidth = 1;\r
+\r
+ for (Index = 0; GetLineByWidth (MenuOption->Description, Width, &GlyphWidth, &Index, &OutputString) != 0x0000;) {\r
+ if ((Temp2 == 0) && (MenuOption->Row >= TopRow) && (MenuOption->Row <= BottomRow) ) {\r
+ PrintStringAt (MenuOption->Col, MenuOption->Row, OutputString);\r
+ }\r
+ //\r
+ // If there is more string to process print on the next row and increment the Skip value\r
+ //\r
+ if (StrLen (&MenuOption->Description[Index]) != 0) {\r
+ if (Temp2 == 0) {\r
+ MenuOption->Row++;\r
+ }\r
+ }\r
+\r
+ FreePool (OutputString);\r
+ if (Temp2 != 0) {\r
+ Temp2--;\r
+ }\r
+ }\r
+\r
+ MenuOption->Row = OriginalRow;\r
+\r
+ }\r
+ }\r
+\r
+ RefreshKeyHelp(gFormData, MenuOption->ThisTag, FALSE);\r
+\r
+ //\r
+ // Clear reverse attribute\r
+ //\r
+ gST->ConOut->SetAttribute (gST->ConOut, GetFieldTextColor ());\r
+ }\r
+ break;\r
+\r
+ case CfUpdateHelpString:\r
+ ControlFlag = CfPrepareToReadKey;\r
+ if ((FormData->Attribute & HII_DISPLAY_MODAL) != 0) {\r
+ break;\r
+ }\r
+\r
+ if (Repaint || NewLine) {\r
+ //\r
+ // Don't print anything if it is a NULL help token\r
+ //\r
+ ASSERT(MenuOption != NULL);\r
+ HelpInfo = ((EFI_IFR_STATEMENT_HEADER *) ((CHAR8 *)MenuOption->ThisTag->OpCode + sizeof (EFI_IFR_OP_HEADER)))->Help;\r
+ if (HelpInfo == 0 || !IsSelectable (MenuOption)) {\r
+ StringPtr = GetToken (STRING_TOKEN (EMPTY_STRING), gHiiHandle);\r
+ } else {\r
+ StringPtr = GetToken (HelpInfo, gFormData->HiiHandle);\r
+ }\r
+\r
+ RowCount = BottomRow - TopRow + 1;\r
+ HelpPageIndex = 0;\r
+ //\r
+ // 1.Calculate how many line the help string need to print.\r
+ //\r
+ if (HelpString != NULL) {\r
+ FreePool (HelpString);\r
+ HelpString = NULL;\r
+ }\r
+ HelpLine = ProcessHelpString (StringPtr, &HelpString, &EachLineWidth, RowCount);\r
+ FreePool (StringPtr);\r
+\r
+ if (HelpLine > RowCount) {\r
+ MultiHelpPage = TRUE;\r
+ StringPtr = GetToken (STRING_TOKEN(ADJUST_HELP_PAGE_UP), gHiiHandle);\r
+ if (HelpHeaderString != NULL) {\r
+ FreePool (HelpHeaderString);\r
+ HelpHeaderString = NULL;\r
+ }\r
+ HelpHeaderLine = ProcessHelpString (StringPtr, &HelpHeaderString, &HeaderLineWidth, 0);\r
+ FreePool (StringPtr);\r
+ StringPtr = GetToken (STRING_TOKEN(ADJUST_HELP_PAGE_DOWN), gHiiHandle);\r
+ if (HelpBottomString != NULL) {\r
+ FreePool (HelpBottomString);\r
+ HelpBottomString = NULL;\r
+ }\r
+ HelpBottomLine = ProcessHelpString (StringPtr, &HelpBottomString, &BottomLineWidth, 0);\r
+ FreePool (StringPtr);\r
+ //\r
+ // Calculate the help page count.\r
+ //\r
+ if (HelpLine > 2 * RowCount - 2) {\r
+ HelpPageCount = (HelpLine - RowCount + 1) / (RowCount - 2) + 1;\r
+ if ((HelpLine - RowCount + 1) % (RowCount - 2) > 1) {\r
+ HelpPageCount += 1;\r
+ }\r
+ } else {\r
+ HelpPageCount = 2;\r
+ }\r
+ } else {\r
+ MultiHelpPage = FALSE;\r
+ }\r
+ }\r
+\r
+ //\r
+ // Check whether need to show the 'More(U/u)' at the begin.\r
+ // Base on current direct info, here shows aligned to the right side of the column.\r
+ // If the direction is multi line and aligned to right side may have problem, so \r
+ // add ASSERT code here.\r
+ //\r
+ if (HelpPageIndex > 0) {\r
+ gST->ConOut->SetAttribute (gST->ConOut, GetInfoTextColor ());\r
+ for (Index = 0; Index < HelpHeaderLine; Index++) {\r
+ ASSERT (HelpHeaderLine == 1);\r
+ ASSERT (GetStringWidth (HelpHeaderString) / 2 < (UINTN) (gHelpBlockWidth - 1));\r
+ PrintStringAtWithWidth (\r
+ gStatementDimensions.RightColumn - gHelpBlockWidth,\r
+ Index + TopRow,\r
+ gEmptyString,\r
+ gHelpBlockWidth\r
+ );\r
+ PrintStringAt (\r
+ gStatementDimensions.RightColumn - GetStringWidth (HelpHeaderString) / 2 - 1,\r
+ Index + TopRow,\r
+ &HelpHeaderString[Index * HeaderLineWidth]\r
+ );\r
+ }\r
+ }\r
+\r
+ gST->ConOut->SetAttribute (gST->ConOut, GetHelpTextColor ());\r
+ //\r
+ // Print the help string info.\r
+ //\r
+ if (!MultiHelpPage) {\r
+ for (Index = 0; Index < HelpLine; Index++) {\r
+ PrintStringAtWithWidth (\r
+ gStatementDimensions.RightColumn - gHelpBlockWidth,\r
+ Index + TopRow,\r
+ &HelpString[Index * EachLineWidth],\r
+ gHelpBlockWidth\r
+ );\r
+ }\r
+ for (; Index < RowCount; Index ++) {\r
+ PrintStringAtWithWidth (\r
+ gStatementDimensions.RightColumn - gHelpBlockWidth,\r
+ Index + TopRow,\r
+ gEmptyString,\r
+ gHelpBlockWidth\r
+ );\r
+ }\r
+ gST->ConOut->SetCursorPosition(gST->ConOut, gStatementDimensions.RightColumn-1, BottomRow);\r
+ } else {\r
+ if (HelpPageIndex == 0) {\r
+ for (Index = 0; Index < RowCount - HelpBottomLine; Index++) {\r
+ PrintStringAtWithWidth (\r
+ gStatementDimensions.RightColumn - gHelpBlockWidth,\r
+ Index + TopRow,\r
+ &HelpString[Index * EachLineWidth],\r
+ gHelpBlockWidth\r
+ );\r
+ }\r
+ } else {\r
+ for (Index = 0; (Index < RowCount - HelpBottomLine - HelpHeaderLine) && \r
+ (Index + HelpPageIndex * (RowCount - 2) + 1 < HelpLine); Index++) {\r
+ PrintStringAtWithWidth (\r
+ gStatementDimensions.RightColumn - gHelpBlockWidth,\r
+ Index + TopRow + HelpHeaderLine,\r
+ &HelpString[(Index + HelpPageIndex * (RowCount - 2) + 1)* EachLineWidth],\r
+ gHelpBlockWidth\r
+ );\r
+ }\r
+ if (HelpPageIndex == HelpPageCount - 1) {\r
+ for (; Index < RowCount - HelpHeaderLine; Index ++) {\r
+ PrintStringAtWithWidth (\r
+ gStatementDimensions.RightColumn - gHelpBlockWidth,\r
+ Index + TopRow + HelpHeaderLine,\r
+ gEmptyString,\r
+ gHelpBlockWidth\r
+ );\r
+ }\r
+ gST->ConOut->SetCursorPosition(gST->ConOut, gStatementDimensions.RightColumn-1, BottomRow);\r
+ }\r
+ } \r
+ }\r
+\r
+ //\r
+ // Check whether need to print the 'More(D/d)' at the bottom.\r
+ // Base on current direct info, here shows aligned to the right side of the column.\r
+ // If the direction is multi line and aligned to right side may have problem, so \r
+ // add ASSERT code here.\r
+ //\r
+ if (HelpPageIndex < HelpPageCount - 1 && MultiHelpPage) {\r
+ gST->ConOut->SetAttribute (gST->ConOut, GetInfoTextColor ());\r
+ for (Index = 0; Index < HelpBottomLine; Index++) {\r
+ ASSERT (HelpBottomLine == 1);\r
+ ASSERT (GetStringWidth (HelpBottomString) / 2 < (UINTN) (gHelpBlockWidth - 1)); \r
+ PrintStringAtWithWidth (\r
+ gStatementDimensions.RightColumn - gHelpBlockWidth,\r
+ BottomRow + Index - HelpBottomLine + 1,\r
+ gEmptyString,\r
+ gHelpBlockWidth\r
+ );\r
+ PrintStringAt (\r
+ gStatementDimensions.RightColumn - GetStringWidth (HelpBottomString) / 2 - 1,\r
+ BottomRow + Index - HelpBottomLine + 1,\r
+ &HelpBottomString[Index * BottomLineWidth]\r
+ );\r
+ }\r
+ }\r
+ //\r
+ // Reset this flag every time we finish using it.\r
+ //\r
+ Repaint = FALSE;\r
+ NewLine = FALSE;\r
+ break;\r
+\r
+ case CfPrepareToReadKey:\r
+ ControlFlag = CfReadKey;\r
+ ScreenOperation = UiNoOperation;\r
+ break;\r
+\r
+ case CfReadKey:\r
+ ControlFlag = CfScreenOperation;\r
+\r
+ //\r
+ // Wait for user's selection\r
+ //\r
+ while (TRUE) {\r
+ Status = gST->ConIn->ReadKeyStroke (gST->ConIn, &Key);\r
+ if (!EFI_ERROR (Status)) {\r
+ EventType = UIEventKey;\r
+ break;\r
+ }\r
+\r
+ //\r
+ // If we encounter error, continue to read another key in.\r
+ //\r
+ if (Status != EFI_NOT_READY) {\r
+ continue;\r
+ }\r
+ \r
+ EventType = UiWaitForEvent(gST->ConIn->WaitForKey);\r
+ if (EventType == UIEventKey) {\r
+ gST->ConIn->ReadKeyStroke (gST->ConIn, &Key);\r
+ }\r
+ break;\r
+ }\r
+\r
+ if (EventType == UIEventDriver) {\r
+ gUserInput->Action = BROWSER_ACTION_NONE;\r
+ ControlFlag = CfExit;\r
+ break;\r
+ }\r
+ \r
+ if (EventType == UIEventTimeOut) {\r
+ gUserInput->Action = BROWSER_ACTION_FORM_EXIT;\r
+ ControlFlag = CfExit;\r
+ break;\r
+ }\r
+\r
+ switch (Key.UnicodeChar) {\r
+ case CHAR_CARRIAGE_RETURN:\r
+ if(MenuOption == NULL || MenuOption->GrayOut || MenuOption->ReadOnly) {\r
+ ControlFlag = CfReadKey;\r
+ break;\r
+ }\r
+\r
+ ScreenOperation = UiSelect;\r
+ gDirection = 0;\r
+ break;\r
+\r
+ //\r
+ // We will push the adjustment of these numeric values directly to the input handler\r
+ // NOTE: we won't handle manual input numeric\r
+ //\r
+ case '+':\r
+ case '-':\r
+ //\r
+ // If the screen has no menu items, and the user didn't select UiReset\r
+ // ignore the selection and go back to reading keys.\r
+ //\r
+ if(IsListEmpty (&gMenuOption) || MenuOption->GrayOut || MenuOption->ReadOnly) {\r
+ ControlFlag = CfReadKey;\r
+ break;\r
+ }\r
+\r
+ ASSERT(MenuOption != NULL);\r
+ Statement = MenuOption->ThisTag;\r
+ if ((Statement->OpCode->OpCode == EFI_IFR_DATE_OP)\r
+ || (Statement->OpCode->OpCode == EFI_IFR_TIME_OP)\r
+ || ((Statement->OpCode->OpCode == EFI_IFR_NUMERIC_OP) && (GetFieldFromNum(Statement->OpCode) != 0))\r
+ ){\r
+ if (Key.UnicodeChar == '+') {\r
+ gDirection = SCAN_RIGHT;\r
+ } else {\r
+ gDirection = SCAN_LEFT;\r
+ }\r
+ \r
+ Status = ProcessOptions (MenuOption, TRUE, &OptionString, TRUE);\r
+ if (OptionString != NULL) {\r
+ FreePool (OptionString);\r
+ }\r
+ if (EFI_ERROR (Status)) {\r
+ //\r
+ // Repaint to clear possible error prompt pop-up\r
+ //\r
+ Repaint = TRUE;\r
+ NewLine = TRUE;\r
+ } else {\r
+ ControlFlag = CfExit;\r
+ }\r
+ }\r
+ break;\r
+\r
+ case '^':\r
+ ScreenOperation = UiUp;\r
+ break;\r
+\r
+ case 'V':\r
+ case 'v':\r
+ ScreenOperation = UiDown;\r
+ break;\r
+\r
+ case ' ':\r
+ if(IsListEmpty (&gMenuOption)) {\r
+ ControlFlag = CfReadKey;\r
+ break;\r
+ }\r
+ \r
+ ASSERT(MenuOption != NULL);\r
+ if (MenuOption->ThisTag->OpCode->OpCode == EFI_IFR_CHECKBOX_OP && !MenuOption->GrayOut && !MenuOption->ReadOnly) {\r
+ ScreenOperation = UiSelect;\r
+ }\r
+ break;\r
+\r
+ case 'D':\r
+ case 'd':\r
+ if (!MultiHelpPage) {\r
+ ControlFlag = CfReadKey;\r
+ break;\r
+ }\r
+ ControlFlag = CfUpdateHelpString;\r
+ HelpPageIndex = HelpPageIndex < HelpPageCount - 1 ? HelpPageIndex + 1 : HelpPageCount - 1;\r
+ break;\r
+\r
+ case 'U':\r
+ case 'u':\r
+ if (!MultiHelpPage) {\r
+ ControlFlag = CfReadKey;\r
+ break;\r
+ }\r
+ ControlFlag = CfUpdateHelpString;\r
+ HelpPageIndex = HelpPageIndex > 0 ? HelpPageIndex - 1 : 0;\r
+ break;\r
+\r
+ case CHAR_NULL:\r
+ for (Index = 0; Index < mScanCodeNumber; Index++) {\r
+ if (Key.ScanCode == gScanCodeToOperation[Index].ScanCode) {\r
+ ScreenOperation = gScanCodeToOperation[Index].ScreenOperation;\r
+ break;\r
+ }\r
+ }\r
+ \r
+ if (((FormData->Attribute & HII_DISPLAY_MODAL) != 0) && (Key.ScanCode == SCAN_ESC || Index == mScanCodeNumber)) {\r
+ //\r
+ // ModalForm has no ESC key and Hot Key.\r
+ //\r
+ ControlFlag = CfReadKey;\r
+ } else if (Index == mScanCodeNumber) {\r
+ //\r
+ // Check whether Key matches the registered hot key.\r
+ //\r
+ HotKey = NULL;\r
+ HotKey = GetHotKeyFromRegisterList (&Key);\r
+ if (HotKey != NULL) {\r
+ ScreenOperation = UiHotKey;\r
+ }\r
+ }\r
+ break;\r
+ }\r
+ break;\r
+\r
+ case CfScreenOperation:\r
+ if (ScreenOperation != UiReset) {\r
+ //\r
+ // If the screen has no menu items, and the user didn't select UiReset\r
+ // ignore the selection and go back to reading keys.\r
+ //\r
+ if (IsListEmpty (&gMenuOption)) {\r
+ ControlFlag = CfReadKey;\r
+ break;\r
+ }\r
+ }\r
+\r
+ for (Index = 0;\r
+ Index < sizeof (gScreenOperationToControlFlag) / sizeof (gScreenOperationToControlFlag[0]);\r
+ Index++\r
+ ) {\r
+ if (ScreenOperation == gScreenOperationToControlFlag[Index].ScreenOperation) {\r
+ ControlFlag = gScreenOperationToControlFlag[Index].ControlFlag;\r
+ break;\r
+ }\r
+ }\r
+ break;\r
+\r
+ case CfUiSelect:\r
+ ControlFlag = CfRepaint;\r
+\r
+ ASSERT(MenuOption != NULL);\r
+ Statement = MenuOption->ThisTag;\r
+ if (Statement->OpCode->OpCode == EFI_IFR_TEXT_OP) {\r
+ break;\r
+ }\r
+\r
+ switch (Statement->OpCode->OpCode) {\r
+ case EFI_IFR_REF_OP:\r
+ case EFI_IFR_ACTION_OP:\r
+ case EFI_IFR_RESET_BUTTON_OP:\r
+ ControlFlag = CfExit;\r
+ break;\r
+\r
+ default:\r
+ //\r
+ // Editable Questions: oneof, ordered list, checkbox, numeric, string, password\r
+ //\r
+ RefreshKeyHelp (gFormData, Statement, TRUE);\r
+ Status = ProcessOptions (MenuOption, TRUE, &OptionString, TRUE);\r
+ \r
+ if (OptionString != NULL) {\r
+ FreePool (OptionString);\r
+ }\r
+ \r
+ if (EFI_ERROR (Status)) {\r
+ Repaint = TRUE;\r
+ NewLine = TRUE;\r
+ RefreshKeyHelp (gFormData, Statement, FALSE);\r
+ break;\r
+ } else {\r
+ ControlFlag = CfExit;\r
+ break;\r
+ }\r
+ }\r
+ break;\r
+\r
+ case CfUiReset:\r
+ //\r
+ // We come here when someone press ESC\r
+ // If the policy is not exit front page when user press ESC, process here.\r
+ //\r
+ if (!FormExitPolicy()) {\r
+ Repaint = TRUE;\r
+ NewLine = TRUE;\r
+ ControlFlag = CfRepaint;\r
+ break;\r
+ }\r
+\r
+ //\r
+ // When user press ESC, it will try to show another menu, should clean the gSequence info.\r
+ //\r
+ if (gSequence != 0) {\r
+ gSequence = 0;\r
+ }\r
+\r
+ gUserInput->Action = BROWSER_ACTION_FORM_EXIT;\r
+ ControlFlag = CfExit;\r
+ break;\r
+\r
+ case CfUiHotKey:\r
+ ControlFlag = CfRepaint;\r
+ \r
+ gUserInput->Action = HotKey->Action;\r
+ ControlFlag = CfExit;\r
+ break;\r
+\r
+ case CfUiLeft:\r
+ ControlFlag = CfRepaint;\r
+ ASSERT(MenuOption != NULL);\r
+ if ((MenuOption->ThisTag->OpCode->OpCode == EFI_IFR_DATE_OP) || (MenuOption->ThisTag->OpCode->OpCode == EFI_IFR_TIME_OP)) {\r
+ if (MenuOption->Sequence != 0) {\r
+ //\r
+ // In the middle or tail of the Date/Time op-code set, go left.\r
+ //\r
+ ASSERT(NewPos != NULL);\r
+ NewPos = NewPos->BackLink;\r
+ }\r
+ }\r
+ break;\r
+\r
+ case CfUiRight:\r
+ ControlFlag = CfRepaint;\r
+ ASSERT(MenuOption != NULL);\r
+ if ((MenuOption->ThisTag->OpCode->OpCode == EFI_IFR_DATE_OP) || (MenuOption->ThisTag->OpCode->OpCode == EFI_IFR_TIME_OP)) {\r
+ if (MenuOption->Sequence != 2) {\r
+ //\r
+ // In the middle or tail of the Date/Time op-code set, go left.\r
+ //\r
+ ASSERT(NewPos != NULL);\r
+ NewPos = NewPos->ForwardLink;\r
+ }\r
+ }\r
+ break;\r
+\r
+ case CfUiUp:\r
+ ControlFlag = CfRepaint;\r
+\r
+ SavedListEntry = NewPos;\r
+\r
+ ASSERT(NewPos != NULL);\r
+ //\r
+ // Adjust Date/Time position before we advance forward.\r
+ //\r
+ AdjustDateAndTimePosition (TRUE, &NewPos);\r
+ if (NewPos->BackLink != &gMenuOption) {\r
+ MenuOption = MENU_OPTION_FROM_LINK (NewPos);\r
+ ASSERT (MenuOption != NULL);\r
+ NewLine = TRUE;\r
+ NewPos = NewPos->BackLink;\r
+\r
+ PreviousMenuOption = MENU_OPTION_FROM_LINK (NewPos);\r
+ if (PreviousMenuOption->Row == 0) {\r
+ UpdateOptionSkipLines (PreviousMenuOption);\r
+ }\r
+ DistanceValue = PreviousMenuOption->Skip;\r
+ Difference = 0;\r
+ if (MenuOption->Row >= DistanceValue + TopRow) {\r
+ Difference = MoveToNextStatement (TRUE, &NewPos, MenuOption->Row - TopRow - DistanceValue);\r
+ }\r
+ NextMenuOption = MENU_OPTION_FROM_LINK (NewPos);\r
+ \r
+ if (Difference < 0) {\r
+ //\r
+ // We hit the begining MenuOption that can be focused\r
+ // so we simply scroll to the top.\r
+ //\r
+ if (TopOfScreen != gMenuOption.ForwardLink) {\r
+ TopOfScreen = gMenuOption.ForwardLink;\r
+ Repaint = TRUE;\r
+ } else {\r
+ //\r
+ // Scroll up to the last page when we have arrived at top page.\r
+ //\r
+ NewPos = &gMenuOption;\r
+ TopOfScreen = &gMenuOption;\r
+ MenuOption = MENU_OPTION_FROM_LINK (SavedListEntry);\r
+ ScreenOperation = UiPageUp;\r
+ ControlFlag = CfScreenOperation;\r
+ break;\r
+ }\r
+ } else if (MenuOption->Row < TopRow + DistanceValue + Difference) {\r
+ //\r
+ // Previous focus MenuOption is above the TopOfScreen, so we need to scroll\r
+ //\r
+ TopOfScreen = NewPos;\r
+ Repaint = TRUE;\r
+ SkipValue = 0;\r
+ } else if (!IsSelectable (NextMenuOption)) {\r
+ //\r
+ // Continue to go up until scroll to next page or the selectable option is found.\r
+ //\r
+ ScreenOperation = UiUp;\r
+ ControlFlag = CfScreenOperation;\r
+ }\r
+\r
+ //\r
+ // If we encounter a Date/Time op-code set, rewind to the first op-code of the set.\r
+ //\r
+ AdjustDateAndTimePosition (TRUE, &TopOfScreen);\r
+ AdjustDateAndTimePosition (TRUE, &NewPos);\r
+ MenuOption = MENU_OPTION_FROM_LINK (SavedListEntry);\r
+ UpdateStatusBar (INPUT_ERROR, FALSE);\r
+ } else {\r
+ //\r
+ // Scroll up to the last page.\r
+ //\r
+ NewPos = &gMenuOption;\r
+ TopOfScreen = &gMenuOption;\r
+ MenuOption = MENU_OPTION_FROM_LINK (SavedListEntry);\r
+ ScreenOperation = UiPageUp;\r
+ ControlFlag = CfScreenOperation;\r
+ }\r
+ break;\r
+\r
+ case CfUiPageUp:\r
+ //\r
+ // SkipValue means lines is skipped when show the top menu option.\r
+ //\r
+ ControlFlag = CfRepaint;\r
+\r
+ ASSERT(NewPos != NULL);\r
+ //\r
+ // Already at the first menu option, Check the skip value.\r
+ //\r
+ if (NewPos->BackLink == &gMenuOption) {\r
+ if (SkipValue == 0) {\r
+ NewLine = FALSE;\r
+ Repaint = FALSE;\r
+ } else {\r
+ NewLine = TRUE;\r
+ Repaint = TRUE;\r
+ SkipValue = 0;\r
+ }\r
+ break;\r
+ }\r
+\r
+ NewLine = TRUE;\r
+ Repaint = TRUE;\r
+\r
+ //\r
+ // SkipValue > (BottomRow - TopRow + 1) means current menu has more than one\r
+ // form of options to be show, so just update the SkipValue to show the next\r
+ // parts of options.\r
+ //\r
+ if (SkipValue > (INTN) (BottomRow - TopRow + 1)) {\r
+ SkipValue -= BottomRow - TopRow + 1;\r
+ break;\r
+ }\r
+\r
+ Link = TopOfScreen;\r
+ //\r
+ // First minus the menu of the top screen, it's value is SkipValue.\r
+ //\r
+ Index = (BottomRow + 1) - SkipValue;\r
+ while ((Index > TopRow) && (Link->BackLink != &gMenuOption)) {\r
+ Link = Link->BackLink;\r
+ PreviousMenuOption = MENU_OPTION_FROM_LINK (Link);\r
+ if (PreviousMenuOption->Row == 0) {\r
+ UpdateOptionSkipLines (PreviousMenuOption);\r
+ } \r
+ if (Index < PreviousMenuOption->Skip) {\r
+ break;\r
+ }\r
+ Index = Index - PreviousMenuOption->Skip;\r
+ }\r
+ \r
+ if ((Link->BackLink == &gMenuOption) && (Index >= TopRow)) {\r
+ SkipValue = 0;\r
+ if (TopOfScreen == &gMenuOption) {\r
+ TopOfScreen = gMenuOption.ForwardLink;\r
+ NewPos = gMenuOption.BackLink;\r
+ MoveToNextStatement (TRUE, &NewPos, BottomRow - TopRow);\r
+ Repaint = FALSE;\r
+ } else if (TopOfScreen != Link) {\r
+ TopOfScreen = Link;\r
+ NewPos = Link;\r
+ MoveToNextStatement (FALSE, &NewPos, BottomRow - TopRow);\r
+ } else {\r
+ //\r
+ // Finally we know that NewPos is the last MenuOption can be focused.\r
+ //\r
+ Repaint = FALSE;\r
+ NewPos = Link;\r
+ MoveToNextStatement (FALSE, &NewPos, BottomRow - TopRow);\r
+ }\r
+ } else {\r
+ if (Index > TopRow) {\r
+ //\r
+ // At here, only case "Index < PreviousMenuOption->Skip" can reach here.\r
+ //\r
+ SkipValue = PreviousMenuOption->Skip - (Index - TopRow);\r
+ } else if (Index == TopRow) {\r
+ SkipValue = 0;\r
+ } else {\r
+ SkipValue = TopRow - Index;\r
+ }\r
+\r
+ //\r
+ // Move to the option in Next page.\r
+ //\r
+ if (TopOfScreen == &gMenuOption) {\r
+ NewPos = gMenuOption.BackLink;\r
+ MoveToNextStatement (TRUE, &NewPos, BottomRow - TopRow);\r
+ } else {\r
+ NewPos = Link;\r
+ MoveToNextStatement (FALSE, &NewPos, BottomRow - TopRow);\r
+ }\r
+\r
+ //\r
+ // There are more MenuOption needing scrolling up.\r
+ //\r
+ TopOfScreen = Link;\r
+ MenuOption = NULL;\r
+ }\r
+\r
+ //\r
+ // If we encounter a Date/Time op-code set, rewind to the first op-code of the set.\r
+ // Don't do this when we are already in the first page.\r
+ //\r
+ AdjustDateAndTimePosition (TRUE, &TopOfScreen);\r
+ AdjustDateAndTimePosition (TRUE, &NewPos);\r
+ break;\r
+\r
+ case CfUiPageDown:\r
+ //\r
+ // SkipValue means lines is skipped when show the top menu option.\r
+ //\r
+ ControlFlag = CfRepaint;\r
+\r
+ ASSERT (NewPos != NULL);\r
+ if (NewPos->ForwardLink == &gMenuOption) {\r
+ NewLine = FALSE;\r
+ Repaint = FALSE;\r
+ break;\r
+ }\r
+\r
+ NewLine = TRUE;\r
+ Repaint = TRUE;\r
+ Link = TopOfScreen;\r
+ NextMenuOption = MENU_OPTION_FROM_LINK (Link);\r
+ Index = TopRow + NextMenuOption->Skip - SkipValue;\r
+ //\r
+ // Count to the menu option which will show at the top of the next form.\r
+ //\r
+ while ((Index <= BottomRow + 1) && (Link->ForwardLink != &gMenuOption)) {\r
+ Link = Link->ForwardLink;\r
+ NextMenuOption = MENU_OPTION_FROM_LINK (Link);\r
+ Index = Index + NextMenuOption->Skip;\r
+ }\r
+\r
+ if ((Link->ForwardLink == &gMenuOption) && (Index <= BottomRow + 1)) {\r
+ //\r
+ // Finally we know that NewPos is the last MenuOption can be focused.\r
+ //\r
+ Repaint = FALSE;\r
+ MoveToNextStatement (TRUE, &Link, Index - TopRow);\r
+ } else {\r
+ //\r
+ // Calculate the skip line for top of screen menu.\r
+ //\r
+ if (Link == TopOfScreen) {\r
+ //\r
+ // The top of screen menu option occupies the entire form.\r
+ //\r
+ SkipValue += BottomRow - TopRow + 1;\r
+ } else {\r
+ SkipValue = NextMenuOption->Skip - (Index - (BottomRow + 1));\r
+ }\r
+\r
+ TopOfScreen = Link;\r
+ MenuOption = NULL;\r
+ //\r
+ // Move to the Next selectable menu.\r
+ //\r
+ MoveToNextStatement (FALSE, &Link, BottomRow - TopRow);\r
+ }\r
+\r
+ //\r
+ // Save the menu as the next highlight menu.\r
+ //\r
+ NewPos = Link;\r
+\r
+ //\r
+ // If we encounter a Date/Time op-code set, rewind to the first op-code of the set.\r
+ // Don't do this when we are already in the last page.\r
+ //\r
+ AdjustDateAndTimePosition (TRUE, &TopOfScreen);\r
+ AdjustDateAndTimePosition (TRUE, &NewPos);\r
+ break;\r
+\r
+ case CfUiDown:\r
+ //\r
+ // SkipValue means lines is skipped when show the top menu option.\r
+ // NewPos points to the menu which is highlighted now.\r
+ //\r
+ ControlFlag = CfRepaint;\r
+\r
+ //\r
+ // Since the behavior of hitting the down arrow on a Date/Time op-code is intended\r
+ // to be one that progresses to the next set of op-codes, we need to advance to the last\r
+ // Date/Time op-code and leave the remaining logic in UiDown intact so the appropriate\r
+ // checking can be done. The only other logic we need to introduce is that if a Date/Time\r
+ // op-code is the last entry in the menu, we need to rewind back to the first op-code of\r
+ // the Date/Time op-code.\r
+ //\r
+ SavedListEntry = NewPos;\r
+ AdjustDateAndTimePosition (FALSE, &NewPos);\r
+\r
+ if (NewPos->ForwardLink != &gMenuOption) {\r
+ MenuOption = MENU_OPTION_FROM_LINK (NewPos);\r
+ NewLine = TRUE;\r
+ NewPos = NewPos->ForwardLink;\r
+\r
+ Difference = 0;\r
+ //\r
+ // Current menu not at the bottom of the form.\r
+ //\r
+ if (BottomRow >= MenuOption->Row + MenuOption->Skip) {\r
+ //\r
+ // Find the next selectable menu.\r
+ //\r
+ Difference = MoveToNextStatement (FALSE, &NewPos, BottomRow - MenuOption->Row - MenuOption->Skip);\r
+ //\r
+ // We hit the end of MenuOption that can be focused\r
+ // so we simply scroll to the first page.\r
+ //\r
+ if (Difference < 0) {\r
+ //\r
+ // Scroll to the first page.\r
+ //\r
+ if (TopOfScreen != gMenuOption.ForwardLink) {\r
+ TopOfScreen = gMenuOption.ForwardLink;\r
+ Repaint = TRUE;\r
+ MenuOption = NULL;\r
+ } else {\r
+ MenuOption = MENU_OPTION_FROM_LINK (SavedListEntry);\r
+ }\r
+ NewPos = gMenuOption.ForwardLink;\r
+ MoveToNextStatement (FALSE, &NewPos, BottomRow - TopRow);\r
+\r
+ SkipValue = 0;\r
+ //\r
+ // If we are at the end of the list and sitting on a Date/Time op, rewind to the head.\r
+ //\r
+ AdjustDateAndTimePosition (TRUE, &TopOfScreen);\r
+ AdjustDateAndTimePosition (TRUE, &NewPos);\r
+ break;\r
+ }\r
+ }\r
+ NextMenuOption = MENU_OPTION_FROM_LINK (NewPos);\r
+ if (NextMenuOption->Row == 0) {\r
+ UpdateOptionSkipLines (NextMenuOption);\r
+ }\r
+ DistanceValue = Difference + NextMenuOption->Skip;\r
+\r
+ Temp = MenuOption->Row + MenuOption->Skip + DistanceValue - 1;\r
+ if ((MenuOption->Row + MenuOption->Skip == BottomRow + 1) &&\r
+ (NextMenuOption->ThisTag->OpCode->OpCode == EFI_IFR_DATE_OP ||\r
+ NextMenuOption->ThisTag->OpCode->OpCode == EFI_IFR_TIME_OP)\r
+ ) {\r
+ Temp ++;\r
+ }\r
+\r
+ //\r
+ // If we are going to scroll, update TopOfScreen\r
+ //\r
+ if (Temp > BottomRow) {\r
+ do {\r
+ //\r
+ // Is the current top of screen a zero-advance op-code?\r
+ // If so, keep moving forward till we hit a >0 advance op-code\r
+ //\r
+ SavedMenuOption = MENU_OPTION_FROM_LINK (TopOfScreen);\r
+\r
+ //\r
+ // If bottom op-code is more than one line or top op-code is more than one line\r
+ //\r
+ if ((DistanceValue > 1) || (SavedMenuOption->Skip > 1)) {\r
+ //\r
+ // Is the bottom op-code greater than or equal in size to the top op-code?\r
+ //\r
+ if ((Temp - BottomRow) >= (SavedMenuOption->Skip - SkipValue)) {\r
+ //\r
+ // Skip the top op-code\r
+ //\r
+ TopOfScreen = TopOfScreen->ForwardLink;\r
+ Difference = (Temp - BottomRow) - (SavedMenuOption->Skip - SkipValue);\r
+\r
+ SavedMenuOption = MENU_OPTION_FROM_LINK (TopOfScreen);\r
+\r
+ //\r
+ // If we have a remainder, skip that many more op-codes until we drain the remainder\r
+ //\r
+ while (Difference >= (INTN) SavedMenuOption->Skip) {\r
+ //\r
+ // Since the Difference is greater than or equal to this op-code's skip value, skip it\r
+ //\r
+ Difference = Difference - (INTN) SavedMenuOption->Skip;\r
+ TopOfScreen = TopOfScreen->ForwardLink;\r
+ SavedMenuOption = MENU_OPTION_FROM_LINK (TopOfScreen);\r
+ }\r
+ //\r
+ // Since we will act on this op-code in the next routine, and increment the\r
+ // SkipValue, set the skips to one less than what is required.\r
+ //\r
+ SkipValue = Difference - 1;\r
+ } else {\r
+ //\r
+ // Since we will act on this op-code in the next routine, and increment the\r
+ // SkipValue, set the skips to one less than what is required.\r
+ //\r
+ SkipValue += (Temp - BottomRow) - 1;\r
+ }\r
+ } else {\r
+ if ((SkipValue + 1) == (INTN) SavedMenuOption->Skip) {\r
+ TopOfScreen = TopOfScreen->ForwardLink;\r
+ break;\r
+ }\r
+ }\r
+ //\r
+ // If the op-code at the top of the screen is more than one line, let's not skip it yet\r
+ // Let's set a skip flag to smoothly scroll the top of the screen.\r
+ //\r
+ if (SavedMenuOption->Skip > 1) {\r
+ if (SavedMenuOption == NextMenuOption) {\r
+ SkipValue = 0;\r
+ } else {\r
+ SkipValue++;\r
+ }\r
+ } else if (SavedMenuOption->Skip == 1) {\r
+ SkipValue = 0;\r
+ } else {\r
+ SkipValue = 0;\r
+ TopOfScreen = TopOfScreen->ForwardLink;\r
+ }\r
+ } while (SavedMenuOption->Skip == 0);\r
+\r
+ Repaint = TRUE;\r
+ } else if (!IsSelectable (NextMenuOption)) {\r
+ //\r
+ // Continue to go down until scroll to next page or the selectable option is found.\r
+ //\r
+ ScreenOperation = UiDown;\r
+ ControlFlag = CfScreenOperation;\r
+ }\r
+\r
+ MenuOption = MENU_OPTION_FROM_LINK (SavedListEntry);\r
+\r
+ UpdateStatusBar (INPUT_ERROR, FALSE);\r
+\r
+ } else {\r
+ //\r
+ // Scroll to the first page.\r
+ //\r
+ if (TopOfScreen != gMenuOption.ForwardLink) {\r
+ TopOfScreen = gMenuOption.ForwardLink;\r
+ Repaint = TRUE;\r
+ MenuOption = NULL;\r
+ } else {\r
+ //\r
+ // Need to remove the current highlight menu.\r
+ // MenuOption saved the last highlight menu info.\r
+ //\r
+ MenuOption = MENU_OPTION_FROM_LINK (SavedListEntry);\r
+ }\r
+\r
+ SkipValue = 0;\r
+ NewLine = TRUE;\r
+ //\r
+ // Get the next highlight menu.\r
+ //\r
+ NewPos = gMenuOption.ForwardLink;\r
+ MoveToNextStatement (FALSE, &NewPos, BottomRow - TopRow);\r
+ }\r
+\r
+ //\r
+ // If we are at the end of the list and sitting on a Date/Time op, rewind to the head.\r
+ //\r
+ AdjustDateAndTimePosition (TRUE, &TopOfScreen);\r
+ AdjustDateAndTimePosition (TRUE, &NewPos);\r
+ break;\r
+\r
+ case CfUiNoOperation:\r
+ ControlFlag = CfRepaint;\r
+ break;\r
+\r
+ case CfExit:\r
+ gST->ConOut->SetAttribute (gST->ConOut, EFI_TEXT_ATTR (EFI_LIGHTGRAY, EFI_BLACK));\r
+ if (HelpString != NULL) {\r
+ FreePool (HelpString);\r
+ }\r
+ if (HelpHeaderString != NULL) {\r
+ FreePool (HelpHeaderString);\r
+ }\r
+ if (HelpBottomString != NULL) {\r
+ FreePool (HelpBottomString);\r
+ }\r
+ return EFI_SUCCESS;\r
+\r
+ default:\r
+ break;\r
+ }\r
+ }\r
+}\r
+\r
+/**\r
+\r
+ Base on the browser status info to show an pop up message.\r
+\r
+**/\r
+VOID\r
+BrowserStatusProcess (\r
+ VOID\r
+ )\r
+{\r
+ CHAR16 *ErrorInfo;\r
+ EFI_INPUT_KEY Key;\r
+\r
+ if (gFormData->BrowserStatus == BROWSER_SUCCESS) {\r
+ return;\r
+ }\r
+\r
+ if (gFormData->ErrorString != NULL) {\r
+ ErrorInfo = gFormData->ErrorString;\r
+ } else {\r
+ switch (gFormData->BrowserStatus) {\r
+ case BROWSER_SUBMIT_FAIL:\r
+ ErrorInfo = gSaveFailed;\r
+ break;\r
+\r
+ case BROWSER_NO_SUBMIT_IF:\r
+ ErrorInfo = gNoSubmitIf;\r
+ break;\r
+\r
+ case BROWSER_FORM_NOT_FOUND:\r
+ ErrorInfo = gFormNotFound;\r
+ break;\r
+\r
+ case BROWSER_FORM_SUPPRESS:\r
+ ErrorInfo = gFormSuppress;\r
+ break;\r
+\r
+ case BROWSER_PROTOCOL_NOT_FOUND:\r
+ ErrorInfo = gProtocolNotFound;\r
+ break;\r
+\r
+ default:\r
+ ErrorInfo = gBrwoserError;\r
+ break;\r
+ }\r
+ }\r
+\r
+ //\r
+ // Error occur, prompt error message.\r
+ //\r
+ do {\r
+ CreateDialog (&Key, gEmptyString, ErrorInfo, gPressEnter, gEmptyString, NULL);\r
+ } while (Key.UnicodeChar != CHAR_CARRIAGE_RETURN);\r
+}\r
+\r
+/**\r
+ Display one form, and return user input.\r
+ \r
+ @param FormData Form Data to be shown.\r
+ @param UserInputData User input data.\r
+ \r
+ @retval EFI_SUCCESS 1.Form Data is shown, and user input is got.\r
+ 2.Error info has show and return.\r
+ @retval EFI_INVALID_PARAMETER The input screen dimension is not valid\r
+ @retval EFI_NOT_FOUND New form data has some error.\r
+**/\r
+EFI_STATUS\r
+EFIAPI \r
+FormDisplay (\r
+ IN FORM_DISPLAY_ENGINE_FORM *FormData,\r
+ OUT USER_INPUT *UserInputData\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+\r
+ ASSERT (FormData != NULL);\r
+ if (FormData == NULL) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ gUserInput = UserInputData;\r
+ gFormData = FormData;\r
+\r
+ //\r
+ // Process the status info first.\r
+ //\r
+ BrowserStatusProcess();\r
+ if (UserInputData == NULL) {\r
+ //\r
+ // UserInputData == NULL, means only need to print the error info, return here.\r
+ //\r
+ return EFI_SUCCESS;\r
+ }\r
+\r
+ ConvertStatementToMenu();\r
+\r
+ Status = DisplayPageFrame (FormData, &gStatementDimensions);\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ //\r
+ // Check whether layout is changed.\r
+ //\r
+ if (mIsFirstForm \r
+ || (gOldFormEntry.HiiHandle != FormData->HiiHandle)\r
+ || (!CompareGuid (&gOldFormEntry.FormSetGuid, &FormData->FormSetGuid))\r
+ || (gOldFormEntry.FormId != FormData->FormId)) {\r
+ mStatementLayoutIsChanged = TRUE;\r
+ } else {\r
+ mStatementLayoutIsChanged = FALSE;\r
+ }\r
+\r
+ Status = UiDisplayMenu(FormData);\r
+ \r
+ //\r
+ // Backup last form info.\r
+ //\r
+ mIsFirstForm = FALSE;\r
+ gOldFormEntry.HiiHandle = FormData->HiiHandle;\r
+ CopyGuid (&gOldFormEntry.FormSetGuid, &FormData->FormSetGuid);\r
+ gOldFormEntry.FormId = FormData->FormId;\r
+\r
+ return Status;\r
+}\r
+\r
+/**\r
+ Clear Screen to the initial state.\r
+**/\r
+VOID\r
+EFIAPI \r
+DriverClearDisplayPage (\r
+ VOID\r
+ )\r
+{\r
+ ClearDisplayPage ();\r
+ mIsFirstForm = TRUE;\r
+}\r
+\r
+/**\r
+ Set Buffer to Value for Size bytes.\r
+\r
+ @param Buffer Memory to set.\r
+ @param Size Number of bytes to set\r
+ @param Value Value of the set operation.\r
+\r
+**/\r
+VOID\r
+SetUnicodeMem (\r
+ IN VOID *Buffer,\r
+ IN UINTN Size,\r
+ IN CHAR16 Value\r
+ )\r
+{\r
+ CHAR16 *Ptr;\r
+\r
+ Ptr = Buffer;\r
+ while ((Size--) != 0) {\r
+ *(Ptr++) = Value;\r
+ }\r
+}\r
+\r
+/**\r
+ Initialize Setup Browser driver.\r
+\r
+ @param ImageHandle The image handle.\r
+ @param SystemTable The system table.\r
+\r
+ @retval EFI_SUCCESS The Setup Browser module is initialized correctly..\r
+ @return Other value if failed to initialize the Setup Browser module.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+InitializeDisplayEngine (\r
+ IN EFI_HANDLE ImageHandle,\r
+ IN EFI_SYSTEM_TABLE *SystemTable\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ EFI_INPUT_KEY HotKey;\r
+ EFI_STRING NewString;\r
+ EDKII_FORM_BROWSER_EXTENSION2_PROTOCOL *FormBrowserEx2;\r
+\r
+ //\r
+ // Publish our HII data\r
+ //\r
+ gHiiHandle = HiiAddPackages (\r
+ &gDisplayEngineGuid,\r
+ ImageHandle,\r
+ DisplayEngineStrings,\r
+ NULL\r
+ );\r
+ ASSERT (gHiiHandle != NULL);\r
+\r
+ //\r
+ // Install Form Display protocol\r
+ //\r
+ Status = gBS->InstallProtocolInterface (\r
+ &mPrivateData.Handle,\r
+ &gEdkiiFormDisplayEngineProtocolGuid,\r
+ EFI_NATIVE_INTERFACE,\r
+ &mPrivateData.FromDisplayProt\r
+ );\r
+ ASSERT_EFI_ERROR (Status);\r
+\r
+ InitializeDisplayStrings();\r
+ \r
+ ZeroMem (&gHighligthMenuInfo, sizeof (gHighligthMenuInfo));\r
+ ZeroMem (&gOldFormEntry, sizeof (gOldFormEntry));\r
+\r
+ //\r
+ // Use BrowserEx2 protocol to register HotKey.\r
+ // \r
+ Status = gBS->LocateProtocol (&gEdkiiFormBrowserEx2ProtocolGuid, NULL, (VOID **) &FormBrowserEx2);\r
+ if (!EFI_ERROR (Status)) {\r
+ //\r
+ // Register the default HotKey F9 and F10 again.\r
+ //\r
+ HotKey.UnicodeChar = CHAR_NULL;\r
+ HotKey.ScanCode = SCAN_F10;\r
+ NewString = HiiGetString (gHiiHandle, STRING_TOKEN (FUNCTION_TEN_STRING), NULL);\r
+ ASSERT (NewString != NULL);\r
+ FormBrowserEx2->RegisterHotKey (&HotKey, BROWSER_ACTION_SUBMIT, 0, NewString);\r
+\r
+ HotKey.ScanCode = SCAN_F9;\r
+ NewString = HiiGetString (gHiiHandle, STRING_TOKEN (FUNCTION_NINE_STRING), NULL);\r
+ ASSERT (NewString != NULL);\r
+ FormBrowserEx2->RegisterHotKey (&HotKey, BROWSER_ACTION_DEFAULT, EFI_HII_DEFAULT_CLASS_STANDARD, NewString);\r
+ }\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+ This is the default unload handle for display core drivers.\r
+\r
+ @param[in] ImageHandle The drivers' driver image.\r
+\r
+ @retval EFI_SUCCESS The image is unloaded.\r
+ @retval Others Failed to unload the image.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+UnloadDisplayEngine (\r
+ IN EFI_HANDLE ImageHandle\r
+ )\r
+{\r
+ HiiRemovePackages(gHiiHandle);\r
+\r
+ FreeDisplayStrings ();\r
+\r
+ return EFI_SUCCESS;\r
+}\r
--- /dev/null
+/** @file\r
+ FormDiplay protocol to show Form\r
+\r
+Copyright (c) 2013, Intel Corporation. All rights reserved.<BR>\r
+This program and the accompanying materials are licensed and made available under \r
+the terms and conditions of the BSD License that accompanies this distribution. \r
+The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php. \r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, \r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#ifndef __FORM_DISPLAY_H__\r
+#define __FORM_DISPLAY_H__\r
+\r
+\r
+#include <Library/UefiBootServicesTableLib.h>\r
+#include <Library/DebugLib.h>\r
+#include <Library/BaseMemoryLib.h>\r
+#include <Library/BaseLib.h>\r
+#include <Library/HiiLib.h>\r
+#include <Library/MemoryAllocationLib.h>\r
+#include <Library/PrintLib.h>\r
+#include <Library/CustomizedDisplayLib.h>\r
+\r
+#include <Protocol/FormBrowserEx2.h>\r
+#include <Protocol/SimpleTextIn.h>\r
+#include <Protocol/DisplayProtocol.h>\r
+\r
+#include <Guid/MdeModuleHii.h>\r
+\r
+//\r
+// This is the generated header file which includes whatever needs to be exported (strings + IFR)\r
+//\r
+extern UINT8 DisplayEngineStrings[];\r
+extern EFI_SCREEN_DESCRIPTOR gStatementDimensions;\r
+extern USER_INPUT *gUserInput;\r
+extern FORM_DISPLAY_ENGINE_FORM *gFormData;\r
+extern EFI_HII_HANDLE gHiiHandle;\r
+extern UINT16 gDirection;\r
+extern LIST_ENTRY gMenuOption;\r
+\r
+//\r
+// Browser Global Strings\r
+//\r
+extern CHAR16 *gSaveFailed;\r
+extern CHAR16 *gPromptForData;\r
+extern CHAR16 *gPromptForPassword;\r
+extern CHAR16 *gPromptForNewPassword;\r
+extern CHAR16 *gConfirmPassword;\r
+extern CHAR16 *gConfirmError;\r
+extern CHAR16 *gPassowordInvalid;\r
+extern CHAR16 *gPressEnter;\r
+extern CHAR16 *gEmptyString;\r
+extern CHAR16 *gMiniString;\r
+extern CHAR16 *gOptionMismatch;\r
+extern CHAR16 *gFormSuppress;\r
+extern CHAR16 *gProtocolNotFound;\r
+\r
+extern CHAR16 gPromptBlockWidth;\r
+extern CHAR16 gOptionBlockWidth;\r
+extern CHAR16 gHelpBlockWidth;\r
+extern CHAR16 *mUnknownString;\r
+\r
+//\r
+// Screen definitions\r
+//\r
+\r
+#define LEFT_SKIPPED_COLUMNS 3\r
+#define SCROLL_ARROW_HEIGHT 1\r
+#define POPUP_PAD_SPACE_COUNT 5\r
+#define POPUP_FRAME_WIDTH 2\r
+\r
+//\r
+// Display definitions\r
+//\r
+#define LEFT_ONEOF_DELIMITER L'<'\r
+#define RIGHT_ONEOF_DELIMITER L'>'\r
+\r
+#define LEFT_NUMERIC_DELIMITER L'['\r
+#define RIGHT_NUMERIC_DELIMITER L']'\r
+\r
+#define LEFT_CHECKBOX_DELIMITER L'['\r
+#define RIGHT_CHECKBOX_DELIMITER L']'\r
+\r
+#define CHECK_ON L'X'\r
+#define CHECK_OFF L' '\r
+\r
+#define TIME_SEPARATOR L':'\r
+#define DATE_SEPARATOR L'/'\r
+\r
+#define SUBTITLE_INDENT 2\r
+\r
+//\r
+// This is the Input Error Message\r
+//\r
+#define INPUT_ERROR 1\r
+\r
+//\r
+// This is the NV RAM update required Message\r
+//\r
+#define NV_UPDATE_REQUIRED 2\r
+//\r
+// Time definitions\r
+//\r
+#define ONE_SECOND 10000000\r
+\r
+//\r
+// It take 23 characters including the NULL to print a 64 bits number with "[" and "]".\r
+// pow(2, 64) = [18446744073709551616]\r
+//\r
+#define MAX_NUMERIC_INPUT_WIDTH 23\r
+\r
+#define EFI_HII_EXPRESSION_INCONSISTENT_IF 0\r
+#define EFI_HII_EXPRESSION_NO_SUBMIT_IF 1\r
+#define EFI_HII_EXPRESSION_GRAY_OUT_IF 2\r
+#define EFI_HII_EXPRESSION_SUPPRESS_IF 3\r
+#define EFI_HII_EXPRESSION_DISABLE_IF 4\r
+\r
+//\r
+// Character definitions\r
+//\r
+#define CHAR_SPACE 0x0020\r
+\r
+#define FORM_DISPLAY_DRIVER_SIGNATURE SIGNATURE_32 ('F', 'D', 'D', 'V')\r
+typedef struct {\r
+ UINT32 Signature;\r
+\r
+ EFI_HANDLE Handle;\r
+\r
+ //\r
+ // Produced protocol\r
+ //\r
+ EDKII_FORM_DISPLAY_ENGINE_PROTOCOL FromDisplayProt;\r
+} FORM_DISPLAY_DRIVER_PRIVATE_DATA;\r
+\r
+\r
+typedef enum {\r
+ UiNoOperation,\r
+ UiSelect,\r
+ UiUp,\r
+ UiDown,\r
+ UiLeft,\r
+ UiRight,\r
+ UiReset,\r
+ UiPrevious,\r
+ UiPageUp,\r
+ UiPageDown,\r
+ UiHotKey,\r
+ UiMaxOperation\r
+} UI_SCREEN_OPERATION;\r
+\r
+typedef enum {\r
+ CfInitialization,\r
+ CfCheckSelection,\r
+ CfRepaint,\r
+ CfRefreshHighLight,\r
+ CfUpdateHelpString,\r
+ CfPrepareToReadKey,\r
+ CfReadKey,\r
+ CfScreenOperation,\r
+ CfUiSelect,\r
+ CfUiReset,\r
+ CfUiLeft,\r
+ CfUiRight,\r
+ CfUiUp,\r
+ CfUiPageUp,\r
+ CfUiPageDown,\r
+ CfUiDown,\r
+ CfUiDefault,\r
+ CfUiNoOperation,\r
+ CfExit,\r
+ CfUiHotKey,\r
+ CfMaxControlFlag\r
+} UI_CONTROL_FLAG;\r
+\r
+typedef enum {\r
+ UIEventNone,\r
+ UIEventKey,\r
+ UIEventTimeOut,\r
+ UIEventDriver\r
+} UI_EVENT_TYPE;\r
+\r
+typedef struct {\r
+ UINT16 ScanCode;\r
+ UI_SCREEN_OPERATION ScreenOperation;\r
+} SCAN_CODE_TO_SCREEN_OPERATION;\r
+\r
+typedef struct {\r
+ UI_SCREEN_OPERATION ScreenOperation;\r
+ UI_CONTROL_FLAG ControlFlag;\r
+} SCREEN_OPERATION_T0_CONTROL_FLAG;\r
+\r
+typedef struct {\r
+ EFI_QUESTION_ID QuestionId;\r
+ UINT16 DisplayRow;\r
+} DISPLAY_HIGHLIGHT_MENU_INFO;\r
+\r
+#define UI_MENU_OPTION_SIGNATURE SIGNATURE_32 ('u', 'i', 'm', 'm')\r
+\r
+typedef struct {\r
+ UINTN Signature;\r
+ LIST_ENTRY Link;\r
+\r
+ EFI_HII_HANDLE Handle;\r
+ FORM_DISPLAY_ENGINE_STATEMENT *ThisTag;\r
+ UINT16 EntryNumber;\r
+\r
+ UINTN Row;\r
+ UINTN Col;\r
+ UINTN OptCol;\r
+ CHAR16 *Description;\r
+ UINTN Skip; // Number of lines\r
+\r
+ //\r
+ // Display item sequence for date/time\r
+ // Date: Month/Day/Year\r
+ // Sequence: 0 1 2\r
+ //\r
+ // Time: Hour : Minute : Second\r
+ // Sequence: 0 1 2\r
+ //\r
+ //\r
+ UINTN Sequence;\r
+\r
+ BOOLEAN GrayOut;\r
+ BOOLEAN ReadOnly;\r
+\r
+ //\r
+ // Whether user could change value of this item\r
+ //\r
+ BOOLEAN IsQuestion;\r
+ BOOLEAN NestInStatement;\r
+} UI_MENU_OPTION;\r
+\r
+#define MENU_OPTION_FROM_LINK(a) CR (a, UI_MENU_OPTION, Link, UI_MENU_OPTION_SIGNATURE)\r
+\r
+/**\r
+ Print Question Value according to it's storage width and display attributes.\r
+\r
+ @param Question The Question to be printed.\r
+ @param FormattedNumber Buffer for output string.\r
+ @param BufferSize The FormattedNumber buffer size in bytes.\r
+\r
+ @retval EFI_SUCCESS Print success.\r
+ @retval EFI_BUFFER_TOO_SMALL Buffer size is not enough for formatted number.\r
+\r
+**/\r
+EFI_STATUS\r
+PrintFormattedNumber (\r
+ IN FORM_DISPLAY_ENGINE_STATEMENT *Question,\r
+ IN OUT CHAR16 *FormattedNumber,\r
+ IN UINTN BufferSize\r
+ );\r
+\r
+/**\r
+ Set value of a data element in an Array by its Index.\r
+\r
+ @param Array The data array.\r
+ @param Type Type of the data in this array.\r
+ @param Index Zero based index for data in this array.\r
+ @param Value The value to be set.\r
+\r
+**/\r
+VOID\r
+SetArrayData (\r
+ IN VOID *Array,\r
+ IN UINT8 Type,\r
+ IN UINTN Index,\r
+ IN UINT64 Value\r
+ );\r
+\r
+/**\r
+ Return data element in an Array by its Index.\r
+\r
+ @param Array The data array.\r
+ @param Type Type of the data in this array.\r
+ @param Index Zero based index for data in this array.\r
+\r
+ @retval Value The data to be returned\r
+\r
+**/\r
+UINT64\r
+GetArrayData (\r
+ IN VOID *Array,\r
+ IN UINT8 Type,\r
+ IN UINTN Index\r
+ );\r
+ \r
+/**\r
+ Search an Option of a Question by its value.\r
+\r
+ @param Question The Question\r
+ @param OptionValue Value for Option to be searched.\r
+\r
+ @retval Pointer Pointer to the found Option.\r
+ @retval NULL Option not found.\r
+\r
+**/\r
+DISPLAY_QUESTION_OPTION *\r
+ValueToOption (\r
+ IN FORM_DISPLAY_ENGINE_STATEMENT *Question,\r
+ IN EFI_HII_VALUE *OptionValue\r
+ );\r
+\r
+/**\r
+ Compare two Hii value.\r
+\r
+ @param Value1 Expression value to compare on left-hand.\r
+ @param Value2 Expression value to compare on right-hand.\r
+ @param Result Return value after compare.\r
+ retval 0 Two operators equal.\r
+ return Positive value if Value1 is greater than Value2.\r
+ retval Negative value if Value1 is less than Value2.\r
+ @param HiiHandle Only required for string compare.\r
+\r
+ @retval other Could not perform compare on two values.\r
+ @retval EFI_SUCCESS Compare the value success.\r
+\r
+**/\r
+EFI_STATUS\r
+CompareHiiValue (\r
+ IN EFI_HII_VALUE *Value1,\r
+ IN EFI_HII_VALUE *Value2,\r
+ OUT INTN *Result,\r
+ IN EFI_HII_HANDLE HiiHandle OPTIONAL\r
+ );\r
+\r
+/**\r
+ Draw a pop up windows based on the dimension, number of lines and\r
+ strings specified.\r
+\r
+ @param RequestedWidth The width of the pop-up.\r
+ @param NumberOfLines The number of lines.\r
+ @param ... A series of text strings that displayed in the pop-up.\r
+\r
+**/\r
+VOID\r
+EFIAPI\r
+CreateMultiStringPopUp (\r
+ IN UINTN RequestedWidth,\r
+ IN UINTN NumberOfLines,\r
+ ...\r
+ );\r
+\r
+/**\r
+ Will copy LineWidth amount of a string in the OutputString buffer and return the\r
+ number of CHAR16 characters that were copied into the OutputString buffer.\r
+ The output string format is:\r
+ Glyph Info + String info + '\0'.\r
+\r
+ In the code, it deals \r,\n,\r\n same as \n\r, also it not process the \r or \g.\r
+\r
+ @param InputString String description for this option.\r
+ @param LineWidth Width of the desired string to extract in CHAR16\r
+ characters\r
+ @param GlyphWidth The glyph width of the begin of the char in the string.\r
+ @param Index Where in InputString to start the copy process\r
+ @param OutputString Buffer to copy the string into\r
+\r
+ @return Returns the number of CHAR16 characters that were copied into the OutputString \r
+ buffer, include extra glyph info and '\0' info.\r
+\r
+**/\r
+UINT16\r
+GetLineByWidth (\r
+ IN CHAR16 *InputString,\r
+ IN UINT16 LineWidth,\r
+ IN OUT UINT16 *GlyphWidth,\r
+ IN OUT UINTN *Index,\r
+ OUT CHAR16 **OutputString\r
+ );\r
+\r
+\r
+/**\r
+ Get the string based on the StringId and HII Package List Handle.\r
+\r
+ @param Token The String's ID.\r
+ @param HiiHandle The Hii handle for this string package.\r
+\r
+ @return The output string.\r
+\r
+**/\r
+CHAR16 *\r
+GetToken (\r
+ IN EFI_STRING_ID Token,\r
+ IN EFI_HII_HANDLE HiiHandle\r
+ );\r
+ \r
+/**\r
+ Count the storage space of a Unicode string.\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
+\r
+ If String is NULL, then ASSERT ().\r
+\r
+ @param String The input string to be counted.\r
+\r
+ @return Storage space for the input string.\r
+\r
+**/\r
+UINTN\r
+GetStringWidth (\r
+ IN CHAR16 *String\r
+ );\r
+\r
+/**\r
+ This routine reads a numeric value from the user input.\r
+\r
+ @param MenuOption Pointer to the current input menu.\r
+\r
+ @retval EFI_SUCCESS If numerical input is read successfully\r
+ @retval EFI_DEVICE_ERROR If operation fails\r
+\r
+**/\r
+EFI_STATUS\r
+GetNumericInput (\r
+ IN UI_MENU_OPTION *MenuOption\r
+ );\r
+\r
+/**\r
+ Get string or password input from user.\r
+\r
+ @param MenuOption Pointer to the current input menu.\r
+ @param Prompt The prompt string shown on popup window.\r
+ @param StringPtr Old user input and destination for use input string.\r
+\r
+ @retval EFI_SUCCESS If string input is read successfully\r
+ @retval EFI_DEVICE_ERROR If operation fails\r
+\r
+**/\r
+EFI_STATUS\r
+ReadString (\r
+ IN UI_MENU_OPTION *MenuOption,\r
+ IN CHAR16 *Prompt,\r
+ IN OUT CHAR16 *StringPtr\r
+ );\r
+\r
+/**\r
+ Draw a pop up windows based on the dimension, number of lines and\r
+ strings specified.\r
+\r
+ @param RequestedWidth The width of the pop-up.\r
+ @param NumberOfLines The number of lines.\r
+ @param Marker The variable argument list for the list of string to be printed.\r
+\r
+**/\r
+VOID\r
+CreateSharedPopUp (\r
+ IN UINTN RequestedWidth,\r
+ IN UINTN NumberOfLines,\r
+ IN VA_LIST Marker\r
+ );\r
+ \r
+/**\r
+ Wait for a key to be pressed by user.\r
+\r
+ @param Key The key which is pressed by user.\r
+\r
+ @retval EFI_SUCCESS The function always completed successfully.\r
+\r
+**/\r
+EFI_STATUS\r
+WaitForKeyStroke (\r
+ OUT EFI_INPUT_KEY *Key\r
+ );\r
+\r
+/**\r
+ Get selection for OneOf and OrderedList (Left/Right will be ignored).\r
+\r
+ @param MenuOption Pointer to the current input menu.\r
+\r
+ @retval EFI_SUCCESS If Option input is processed successfully\r
+ @retval EFI_DEVICE_ERROR If operation fails\r
+\r
+**/\r
+EFI_STATUS\r
+GetSelectionInputPopUp (\r
+ IN UI_MENU_OPTION *MenuOption\r
+ );\r
+\r
+/**\r
+ Process the help string: Split StringPtr to several lines of strings stored in\r
+ FormattedString and the glyph width of each line cannot exceed gHelpBlockWidth.\r
+\r
+ @param StringPtr The entire help string.\r
+ @param FormattedString The oupput formatted string.\r
+ @param EachLineWidth The max string length of each line in the formatted string.\r
+ @param RowCount TRUE: if Question is selected.\r
+\r
+**/\r
+UINTN\r
+ProcessHelpString (\r
+ IN CHAR16 *StringPtr,\r
+ OUT CHAR16 **FormattedString,\r
+ OUT UINT16 *EachLineWidth,\r
+ IN UINTN RowCount\r
+ );\r
+\r
+/**\r
+ Process a Question's Option (whether selected or un-selected).\r
+\r
+ @param MenuOption The MenuOption for this Question.\r
+ @param Selected TRUE: if Question is selected.\r
+ @param OptionString Pointer of the Option String to be displayed.\r
+ @param SkipErrorValue Whether need to return when value without option for it.\r
+\r
+ @retval EFI_SUCCESS Question Option process success.\r
+ @retval Other Question Option process fail.\r
+\r
+**/\r
+EFI_STATUS\r
+ProcessOptions (\r
+ IN UI_MENU_OPTION *MenuOption,\r
+ IN BOOLEAN Selected,\r
+ OUT CHAR16 **OptionString,\r
+ IN BOOLEAN SkipErrorValue\r
+ );\r
+\r
+/**\r
+ Set Buffer to Value for Size bytes.\r
+\r
+ @param Buffer Memory to set.\r
+ @param Size Number of bytes to set\r
+ @param Value Value of the set operation.\r
+\r
+**/\r
+VOID\r
+SetUnicodeMem (\r
+ IN VOID *Buffer,\r
+ IN UINTN Size,\r
+ IN CHAR16 Value\r
+ );\r
+\r
+/**\r
+ Display one form, and return user input.\r
+ \r
+ @param FormData Form Data to be shown.\r
+ @param UserInputData User input data.\r
+ \r
+ @retval EFI_SUCCESS Form Data is shown, and user input is got.\r
+**/\r
+EFI_STATUS\r
+EFIAPI \r
+FormDisplay (\r
+ IN FORM_DISPLAY_ENGINE_FORM *FormData,\r
+ OUT USER_INPUT *UserInputData\r
+ );\r
+\r
+/**\r
+ Clear Screen to the initial state.\r
+**/\r
+VOID\r
+EFIAPI \r
+DriverClearDisplayPage (\r
+ VOID\r
+ );\r
+\r
+/**\r
+ Exit Display and Clear Screen to the original state.\r
+\r
+**/\r
+VOID\r
+EFIAPI \r
+ExitDisplay (\r
+ VOID\r
+ );\r
+\r
+/**\r
+ Process validate for one question.\r
+\r
+ @param Question The question which need to validate.\r
+\r
+ @retval EFI_SUCCESS Question Option process success.\r
+ @retval Other Question Option process fail.\r
+\r
+**/\r
+EFI_STATUS \r
+ValidateQuestion (\r
+ IN FORM_DISPLAY_ENGINE_STATEMENT *Question\r
+ );\r
+\r
+#endif\r
--- /dev/null
+/** @file\r
+Implementation for handling user input from the User Interfaces.\r
+\r
+Copyright (c) 2004 - 2012, 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
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#include "FormDisplay.h"\r
+\r
+/**\r
+ Get maximum and minimum info from this opcode.\r
+\r
+ @param OpCode Pointer to the current input opcode.\r
+ @param Minimum The minimum size info for this opcode.\r
+ @param Maximum The maximum size info for this opcode.\r
+\r
+**/\r
+VOID\r
+GetFieldFromOp (\r
+ IN EFI_IFR_OP_HEADER *OpCode,\r
+ OUT UINTN *Minimum,\r
+ OUT UINTN *Maximum\r
+ )\r
+{\r
+ EFI_IFR_STRING *StringOp;\r
+ EFI_IFR_PASSWORD *PasswordOp;\r
+ if (OpCode->OpCode == EFI_IFR_STRING_OP) {\r
+ StringOp = (EFI_IFR_STRING *) OpCode;\r
+ *Minimum = StringOp->MinSize;\r
+ *Maximum = StringOp->MaxSize; \r
+ } else if (OpCode->OpCode == EFI_IFR_PASSWORD_OP) {\r
+ PasswordOp = (EFI_IFR_PASSWORD *) OpCode;\r
+ *Minimum = PasswordOp->MinSize;\r
+ *Maximum = PasswordOp->MaxSize; \r
+ } else {\r
+ *Minimum = 0;\r
+ *Maximum = 0; \r
+ }\r
+}\r
+\r
+/**\r
+ Get string or password input from user.\r
+\r
+ @param MenuOption Pointer to the current input menu.\r
+ @param Prompt The prompt string shown on popup window.\r
+ @param StringPtr Old user input and destination for use input string.\r
+\r
+ @retval EFI_SUCCESS If string input is read successfully\r
+ @retval EFI_DEVICE_ERROR If operation fails\r
+\r
+**/\r
+EFI_STATUS\r
+ReadString (\r
+ IN UI_MENU_OPTION *MenuOption,\r
+ IN CHAR16 *Prompt,\r
+ IN OUT CHAR16 *StringPtr\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ EFI_INPUT_KEY Key;\r
+ CHAR16 NullCharacter;\r
+ UINTN ScreenSize;\r
+ CHAR16 Space[2];\r
+ CHAR16 KeyPad[2];\r
+ CHAR16 *TempString;\r
+ CHAR16 *BufferedString;\r
+ UINTN Index;\r
+ UINTN Index2;\r
+ UINTN Count;\r
+ UINTN Start;\r
+ UINTN Top;\r
+ UINTN DimensionsWidth;\r
+ UINTN DimensionsHeight;\r
+ UINTN CurrentCursor;\r
+ BOOLEAN CursorVisible;\r
+ UINTN Minimum;\r
+ UINTN Maximum;\r
+ FORM_DISPLAY_ENGINE_STATEMENT *Question;\r
+ BOOLEAN IsPassword;\r
+\r
+ DimensionsWidth = gStatementDimensions.RightColumn - gStatementDimensions.LeftColumn;\r
+ DimensionsHeight = gStatementDimensions.BottomRow - gStatementDimensions.TopRow;\r
+\r
+ NullCharacter = CHAR_NULL;\r
+ ScreenSize = GetStringWidth (Prompt) / sizeof (CHAR16);\r
+ Space[0] = L' ';\r
+ Space[1] = CHAR_NULL;\r
+\r
+ Question = MenuOption->ThisTag;\r
+ GetFieldFromOp(Question->OpCode, &Minimum, &Maximum);\r
+\r
+ if (Question->OpCode->OpCode == EFI_IFR_PASSWORD_OP) {\r
+ IsPassword = TRUE;\r
+ } else {\r
+ IsPassword = FALSE;\r
+ }\r
+\r
+ TempString = AllocateZeroPool ((Maximum + 1)* sizeof (CHAR16));\r
+ ASSERT (TempString);\r
+\r
+ if (ScreenSize < (Maximum + 1)) {\r
+ ScreenSize = Maximum + 1;\r
+ }\r
+\r
+ if ((ScreenSize + 2) > DimensionsWidth) {\r
+ ScreenSize = DimensionsWidth - 2;\r
+ }\r
+\r
+ BufferedString = AllocateZeroPool (ScreenSize * 2);\r
+ ASSERT (BufferedString);\r
+\r
+ Start = (DimensionsWidth - ScreenSize - 2) / 2 + gStatementDimensions.LeftColumn + 1;\r
+ Top = ((DimensionsHeight - 6) / 2) + gStatementDimensions.TopRow - 1;\r
+\r
+ //\r
+ // Display prompt for string\r
+ //\r
+ // CreateDialog (NULL, "", Prompt, Space, "", NULL);\r
+ CreateMultiStringPopUp (ScreenSize, 4, &NullCharacter, Prompt, Space, &NullCharacter);\r
+ gST->ConOut->SetAttribute (gST->ConOut, EFI_TEXT_ATTR (EFI_BLACK, EFI_LIGHTGRAY));\r
+\r
+ CursorVisible = gST->ConOut->Mode->CursorVisible;\r
+ gST->ConOut->EnableCursor (gST->ConOut, TRUE);\r
+\r
+ CurrentCursor = GetStringWidth (StringPtr) / 2 - 1;\r
+ if (CurrentCursor != 0) {\r
+ //\r
+ // Show the string which has beed saved before.\r
+ //\r
+ SetUnicodeMem (BufferedString, ScreenSize - 1, L' ');\r
+ PrintStringAt (Start + 1, Top + 3, BufferedString);\r
+\r
+ if ((GetStringWidth (StringPtr) / 2) > (DimensionsWidth - 2)) {\r
+ Index = (GetStringWidth (StringPtr) / 2) - DimensionsWidth + 2;\r
+ } else {\r
+ Index = 0;\r
+ }\r
+\r
+ if (IsPassword) {\r
+ gST->ConOut->SetCursorPosition (gST->ConOut, Start + 1, Top + 3);\r
+ }\r
+\r
+ for (Count = 0; Index + 1 < GetStringWidth (StringPtr) / 2; Index++, Count++) {\r
+ BufferedString[Count] = StringPtr[Index];\r
+\r
+ if (IsPassword) {\r
+ PrintCharAt ((UINTN)-1, (UINTN)-1, L'*');\r
+ }\r
+ }\r
+\r
+ if (!IsPassword) {\r
+ PrintStringAt (Start + 1, Top + 3, BufferedString);\r
+ }\r
+ \r
+ gST->ConOut->SetAttribute (gST->ConOut, EFI_TEXT_ATTR (EFI_LIGHTGRAY, EFI_BLACK));\r
+ gST->ConOut->SetCursorPosition (gST->ConOut, Start + GetStringWidth (StringPtr) / 2, Top + 3);\r
+ }\r
+ \r
+ do {\r
+ Status = WaitForKeyStroke (&Key);\r
+ ASSERT_EFI_ERROR (Status);\r
+\r
+ gST->ConOut->SetAttribute (gST->ConOut, EFI_TEXT_ATTR (EFI_BLACK, EFI_LIGHTGRAY));\r
+ switch (Key.UnicodeChar) {\r
+ case CHAR_NULL:\r
+ switch (Key.ScanCode) {\r
+ case SCAN_LEFT:\r
+ if (CurrentCursor > 0) {\r
+ CurrentCursor--;\r
+ }\r
+ break;\r
+\r
+ case SCAN_RIGHT:\r
+ if (CurrentCursor < (GetStringWidth (StringPtr) / 2 - 1)) {\r
+ CurrentCursor++;\r
+ }\r
+ break;\r
+\r
+ case SCAN_ESC:\r
+ FreePool (TempString);\r
+ FreePool (BufferedString);\r
+ gST->ConOut->SetAttribute (gST->ConOut, EFI_TEXT_ATTR (EFI_LIGHTGRAY, EFI_BLACK));\r
+ gST->ConOut->EnableCursor (gST->ConOut, CursorVisible);\r
+ return EFI_DEVICE_ERROR;\r
+\r
+ default:\r
+ break;\r
+ }\r
+\r
+ break;\r
+\r
+ case CHAR_CARRIAGE_RETURN:\r
+ if (GetStringWidth (StringPtr) >= ((Minimum + 1) * sizeof (CHAR16))) {\r
+\r
+ FreePool (TempString);\r
+ FreePool (BufferedString);\r
+ gST->ConOut->SetAttribute (gST->ConOut, EFI_TEXT_ATTR (EFI_LIGHTGRAY, EFI_BLACK));\r
+ gST->ConOut->EnableCursor (gST->ConOut, CursorVisible);\r
+ return EFI_SUCCESS;\r
+ } else {\r
+ //\r
+ // Simply create a popup to tell the user that they had typed in too few characters.\r
+ // To save code space, we can then treat this as an error and return back to the menu.\r
+ //\r
+ do {\r
+ CreateDialog (&Key, &NullCharacter, gMiniString, gPressEnter, &NullCharacter, NULL);\r
+ } while (Key.UnicodeChar != CHAR_CARRIAGE_RETURN);\r
+\r
+ FreePool (TempString);\r
+ FreePool (BufferedString);\r
+ gST->ConOut->SetAttribute (gST->ConOut, EFI_TEXT_ATTR (EFI_LIGHTGRAY, EFI_BLACK));\r
+ gST->ConOut->EnableCursor (gST->ConOut, CursorVisible);\r
+ return EFI_DEVICE_ERROR;\r
+ }\r
+\r
+ break;\r
+\r
+ case CHAR_BACKSPACE:\r
+ if (StringPtr[0] != CHAR_NULL && CurrentCursor != 0) {\r
+ for (Index = 0; Index < CurrentCursor - 1; Index++) {\r
+ TempString[Index] = StringPtr[Index];\r
+ }\r
+ Count = GetStringWidth (StringPtr) / 2 - 1;\r
+ if (Count >= CurrentCursor) {\r
+ for (Index = CurrentCursor - 1, Index2 = CurrentCursor; Index2 < Count; Index++, Index2++) {\r
+ TempString[Index] = StringPtr[Index2];\r
+ }\r
+ TempString[Index] = CHAR_NULL;\r
+ }\r
+ //\r
+ // Effectively truncate string by 1 character\r
+ //\r
+ StrCpy (StringPtr, TempString);\r
+ CurrentCursor --;\r
+ }\r
+\r
+ default:\r
+ //\r
+ // If it is the beginning of the string, don't worry about checking maximum limits\r
+ //\r
+ if ((StringPtr[0] == CHAR_NULL) && (Key.UnicodeChar != CHAR_BACKSPACE)) {\r
+ StrnCpy (StringPtr, &Key.UnicodeChar, 1);\r
+ CurrentCursor++;\r
+ } else if ((GetStringWidth (StringPtr) < ((Maximum + 1) * sizeof (CHAR16))) && (Key.UnicodeChar != CHAR_BACKSPACE)) {\r
+ KeyPad[0] = Key.UnicodeChar;\r
+ KeyPad[1] = CHAR_NULL;\r
+ Count = GetStringWidth (StringPtr) / 2 - 1;\r
+ if (CurrentCursor < Count) {\r
+ for (Index = 0; Index < CurrentCursor; Index++) {\r
+ TempString[Index] = StringPtr[Index];\r
+ }\r
+ TempString[Index] = CHAR_NULL;\r
+ StrCat (TempString, KeyPad);\r
+ StrCat (TempString, StringPtr + CurrentCursor);\r
+ StrCpy (StringPtr, TempString);\r
+ } else {\r
+ StrCat (StringPtr, KeyPad);\r
+ }\r
+ CurrentCursor++;\r
+ }\r
+\r
+ //\r
+ // If the width of the input string is now larger than the screen, we nee to\r
+ // adjust the index to start printing portions of the string\r
+ //\r
+ SetUnicodeMem (BufferedString, ScreenSize - 1, L' ');\r
+ PrintStringAt (Start + 1, Top + 3, BufferedString);\r
+\r
+ if ((GetStringWidth (StringPtr) / 2) > (DimensionsWidth - 2)) {\r
+ Index = (GetStringWidth (StringPtr) / 2) - DimensionsWidth + 2;\r
+ } else {\r
+ Index = 0;\r
+ }\r
+\r
+ if (IsPassword) {\r
+ gST->ConOut->SetCursorPosition (gST->ConOut, Start + 1, Top + 3);\r
+ }\r
+\r
+ for (Count = 0; Index + 1 < GetStringWidth (StringPtr) / 2; Index++, Count++) {\r
+ BufferedString[Count] = StringPtr[Index];\r
+\r
+ if (IsPassword) {\r
+ PrintCharAt ((UINTN)-1, (UINTN)-1, L'*');\r
+ }\r
+ }\r
+\r
+ if (!IsPassword) {\r
+ PrintStringAt (Start + 1, Top + 3, BufferedString);\r
+ }\r
+ break;\r
+ }\r
+\r
+ gST->ConOut->SetAttribute (gST->ConOut, EFI_TEXT_ATTR (EFI_LIGHTGRAY, EFI_BLACK));\r
+ gST->ConOut->SetCursorPosition (gST->ConOut, Start + CurrentCursor + 1, Top + 3);\r
+ } while (TRUE);\r
+\r
+}\r
+\r
+/**\r
+ Adjust the value to the correct one. Rules follow the sample:\r
+ like: Year change: 2012.02.29 -> 2013.02.29 -> 2013.02.01\r
+ Month change: 2013.03.29 -> 2013.02.29 -> 2013.02.28\r
+\r
+ @param QuestionValue Pointer to current question.\r
+ @param Sequence The sequence of the field in the question.\r
+**/\r
+VOID\r
+AdjustQuestionValue (\r
+ IN EFI_HII_VALUE *QuestionValue,\r
+ IN UINT8 Sequence\r
+ )\r
+{\r
+ UINT8 Month;\r
+ UINT16 Year;\r
+ UINT8 Maximum;\r
+ UINT8 Minimum;\r
+\r
+ Month = QuestionValue->Value.date.Month;\r
+ Year = QuestionValue->Value.date.Year;\r
+ Minimum = 1;\r
+\r
+ switch (Month) {\r
+ case 2:\r
+ if ((Year % 4) == 0 && ((Year % 100) != 0 || (Year % 400) == 0)) {\r
+ Maximum = 29;\r
+ } else {\r
+ Maximum = 28;\r
+ }\r
+ break;\r
+ case 4:\r
+ case 6:\r
+ case 9:\r
+ case 11:\r
+ Maximum = 30;\r
+ break;\r
+ default:\r
+ Maximum = 31;\r
+ break;\r
+ }\r
+\r
+ //\r
+ // Change the month area.\r
+ //\r
+ if (Sequence == 0) {\r
+ if (QuestionValue->Value.date.Day > Maximum) {\r
+ QuestionValue->Value.date.Day = Maximum;\r
+ }\r
+ }\r
+ \r
+ //\r
+ // Change the Year area.\r
+ //\r
+ if (Sequence == 2) {\r
+ if (QuestionValue->Value.date.Day > Maximum) {\r
+ QuestionValue->Value.date.Day = Minimum;\r
+ }\r
+ }\r
+}\r
+\r
+/**\r
+ Get field info from numeric opcode.\r
+\r
+ @param OpCode Pointer to the current input opcode.\r
+ @param Minimum The minimum size info for this opcode.\r
+ @param Maximum The maximum size info for this opcode.\r
+ @param Step The step size info for this opcode.\r
+ @param StorageWidth The storage width info for this opcode.\r
+\r
+**/\r
+VOID\r
+GetValueFromNum (\r
+ IN EFI_IFR_OP_HEADER *OpCode,\r
+ OUT UINT64 *Minimum,\r
+ OUT UINT64 *Maximum,\r
+ OUT UINT64 *Step,\r
+ OUT UINT16 *StorageWidth\r
+)\r
+{\r
+ EFI_IFR_NUMERIC *NumericOp;\r
+\r
+ NumericOp = (EFI_IFR_NUMERIC *) OpCode;\r
+ \r
+ switch (NumericOp->Flags & EFI_IFR_NUMERIC_SIZE) {\r
+ case EFI_IFR_NUMERIC_SIZE_1:\r
+ *Minimum = NumericOp->data.u8.MinValue;\r
+ *Maximum = NumericOp->data.u8.MaxValue;\r
+ *Step = NumericOp->data.u8.Step;\r
+ *StorageWidth = (UINT16) sizeof (UINT8);\r
+ break;\r
+ \r
+ case EFI_IFR_NUMERIC_SIZE_2:\r
+ *Minimum = NumericOp->data.u16.MinValue;\r
+ *Maximum = NumericOp->data.u16.MaxValue;\r
+ *Step = NumericOp->data.u16.Step;\r
+ *StorageWidth = (UINT16) sizeof (UINT16);\r
+ break;\r
+ \r
+ case EFI_IFR_NUMERIC_SIZE_4:\r
+ *Minimum = NumericOp->data.u32.MinValue;\r
+ *Maximum = NumericOp->data.u32.MaxValue;\r
+ *Step = NumericOp->data.u32.Step;\r
+ *StorageWidth = (UINT16) sizeof (UINT32);\r
+ break;\r
+ \r
+ case EFI_IFR_NUMERIC_SIZE_8:\r
+ *Minimum = NumericOp->data.u64.MinValue;\r
+ *Maximum = NumericOp->data.u64.MaxValue;\r
+ *Step = NumericOp->data.u64.Step;\r
+ *StorageWidth = (UINT16) sizeof (UINT64);\r
+ break;\r
+ \r
+ default:\r
+ break;\r
+ }\r
+\r
+ if (*Maximum == 0) {\r
+ *Maximum = (UINT64) -1;\r
+ }\r
+}\r
+\r
+/**\r
+ This routine reads a numeric value from the user input.\r
+\r
+ @param MenuOption Pointer to the current input menu.\r
+\r
+ @retval EFI_SUCCESS If numerical input is read successfully\r
+ @retval EFI_DEVICE_ERROR If operation fails\r
+\r
+**/\r
+EFI_STATUS\r
+GetNumericInput (\r
+ IN UI_MENU_OPTION *MenuOption\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ UINTN Column;\r
+ UINTN Row;\r
+ CHAR16 InputText[MAX_NUMERIC_INPUT_WIDTH];\r
+ CHAR16 FormattedNumber[MAX_NUMERIC_INPUT_WIDTH - 1];\r
+ UINT64 PreviousNumber[MAX_NUMERIC_INPUT_WIDTH - 3];\r
+ UINTN Count;\r
+ UINTN Loop;\r
+ BOOLEAN ManualInput;\r
+ BOOLEAN HexInput;\r
+ BOOLEAN DateOrTime;\r
+ UINTN InputWidth;\r
+ UINT64 EditValue;\r
+ UINT64 Step;\r
+ UINT64 Minimum;\r
+ UINT64 Maximum;\r
+ UINTN EraseLen;\r
+ UINT8 Digital;\r
+ EFI_INPUT_KEY Key;\r
+ EFI_HII_VALUE *QuestionValue;\r
+ FORM_DISPLAY_ENGINE_STATEMENT *Question;\r
+ EFI_IFR_NUMERIC *NumericOp;\r
+ UINT16 StorageWidth;\r
+\r
+ Column = MenuOption->OptCol;\r
+ Row = MenuOption->Row;\r
+ PreviousNumber[0] = 0;\r
+ Count = 0;\r
+ InputWidth = 0;\r
+ Digital = 0;\r
+ StorageWidth = 0;\r
+ Minimum = 0;\r
+ Maximum = 0;\r
+ NumericOp = NULL;\r
+\r
+ Question = MenuOption->ThisTag;\r
+ QuestionValue = &Question->CurrentValue;\r
+\r
+ //\r
+ // Only two case, user can enter to this function: Enter and +/- case.\r
+ // In Enter case, gDirection = 0; in +/- case, gDirection = SCAN_LEFT/SCAN_WRIGHT\r
+ //\r
+ ManualInput = (BOOLEAN)(gDirection == 0 ? TRUE : FALSE);\r
+\r
+ if ((Question->OpCode->OpCode == EFI_IFR_DATE_OP) || (Question->OpCode->OpCode == EFI_IFR_TIME_OP)) {\r
+ DateOrTime = TRUE;\r
+ } else {\r
+ DateOrTime = FALSE;\r
+ }\r
+\r
+ //\r
+ // Prepare Value to be edit\r
+ //\r
+ EraseLen = 0;\r
+ EditValue = 0;\r
+ if (Question->OpCode->OpCode == EFI_IFR_DATE_OP) {\r
+ Step = 1;\r
+ Minimum = 1;\r
+\r
+ switch (MenuOption->Sequence) {\r
+ case 0:\r
+ Maximum = 12;\r
+ EraseLen = 4;\r
+ EditValue = QuestionValue->Value.date.Month;\r
+ break;\r
+\r
+ case 1:\r
+ switch (QuestionValue->Value.date.Month) {\r
+ case 2:\r
+ if ((QuestionValue->Value.date.Year % 4) == 0 && \r
+ ((QuestionValue->Value.date.Year % 100) != 0 || \r
+ (QuestionValue->Value.date.Year % 400) == 0)) {\r
+ Maximum = 29;\r
+ } else {\r
+ Maximum = 28;\r
+ }\r
+ break;\r
+ case 4:\r
+ case 6:\r
+ case 9:\r
+ case 11:\r
+ Maximum = 30;\r
+ break;\r
+ default:\r
+ Maximum = 31;\r
+ break;\r
+ } \r
+\r
+ EraseLen = 3;\r
+ EditValue = QuestionValue->Value.date.Day;\r
+ break;\r
+\r
+ case 2:\r
+ Maximum = 0xffff;\r
+ EraseLen = 5;\r
+ EditValue = QuestionValue->Value.date.Year;\r
+ break;\r
+\r
+ default:\r
+ break;\r
+ }\r
+ } else if (Question->OpCode->OpCode == EFI_IFR_TIME_OP) {\r
+ Step = 1;\r
+ Minimum = 0;\r
+\r
+ switch (MenuOption->Sequence) {\r
+ case 0:\r
+ Maximum = 23;\r
+ EraseLen = 4;\r
+ EditValue = QuestionValue->Value.time.Hour;\r
+ break;\r
+\r
+ case 1:\r
+ Maximum = 59;\r
+ EraseLen = 3;\r
+ EditValue = QuestionValue->Value.time.Minute;\r
+ break;\r
+\r
+ case 2:\r
+ Maximum = 59;\r
+ EraseLen = 3;\r
+ EditValue = QuestionValue->Value.time.Second;\r
+ break;\r
+\r
+ default:\r
+ break;\r
+ }\r
+ } else {\r
+ ASSERT (Question->OpCode->OpCode == EFI_IFR_NUMERIC_OP);\r
+ NumericOp = (EFI_IFR_NUMERIC *) Question->OpCode;\r
+ GetValueFromNum(Question->OpCode, &Minimum, &Maximum, &Step, &StorageWidth);\r
+ EditValue = QuestionValue->Value.u64;\r
+ EraseLen = gOptionBlockWidth;\r
+ }\r
+\r
+ if ((Question->OpCode->OpCode == EFI_IFR_NUMERIC_OP) && (NumericOp != NULL) &&\r
+ ((NumericOp->Flags & EFI_IFR_DISPLAY) == EFI_IFR_DISPLAY_UINT_HEX)) {\r
+ HexInput = TRUE;\r
+ } else {\r
+ HexInput = FALSE;\r
+ }\r
+\r
+ //\r
+ // Enter from "Enter" input, clear the old word showing.\r
+ //\r
+ if (ManualInput) {\r
+ if (Question->OpCode->OpCode == EFI_IFR_NUMERIC_OP) {\r
+ if (HexInput) {\r
+ InputWidth = StorageWidth * 2;\r
+ } else {\r
+ switch (StorageWidth) {\r
+ case 1:\r
+ InputWidth = 3;\r
+ break;\r
+\r
+ case 2:\r
+ InputWidth = 5;\r
+ break;\r
+\r
+ case 4:\r
+ InputWidth = 10;\r
+ break;\r
+\r
+ case 8:\r
+ InputWidth = 20;\r
+ break;\r
+\r
+ default:\r
+ InputWidth = 0;\r
+ break;\r
+ }\r
+ }\r
+\r
+ InputText[0] = LEFT_NUMERIC_DELIMITER;\r
+ SetUnicodeMem (InputText + 1, InputWidth, L' ');\r
+ ASSERT (InputWidth + 2 < MAX_NUMERIC_INPUT_WIDTH);\r
+ InputText[InputWidth + 1] = RIGHT_NUMERIC_DELIMITER;\r
+ InputText[InputWidth + 2] = L'\0';\r
+\r
+ PrintStringAt (Column, Row, InputText);\r
+ Column++;\r
+ }\r
+\r
+ if (Question->OpCode->OpCode == EFI_IFR_DATE_OP) {\r
+ if (MenuOption->Sequence == 2) {\r
+ InputWidth = 4;\r
+ } else {\r
+ InputWidth = 2;\r
+ }\r
+\r
+ if (MenuOption->Sequence == 0) {\r
+ InputText[0] = LEFT_NUMERIC_DELIMITER;\r
+ SetUnicodeMem (InputText + 1, InputWidth, L' ');\r
+ } else {\r
+ SetUnicodeMem (InputText, InputWidth, L' ');\r
+ }\r
+\r
+ if (MenuOption->Sequence == 2) {\r
+ InputText[InputWidth + 1] = RIGHT_NUMERIC_DELIMITER;\r
+ } else {\r
+ InputText[InputWidth + 1] = DATE_SEPARATOR;\r
+ }\r
+ InputText[InputWidth + 2] = L'\0';\r
+\r
+ PrintStringAt (Column, Row, InputText);\r
+ if (MenuOption->Sequence == 0) {\r
+ Column++;\r
+ }\r
+ }\r
+\r
+ if (Question->OpCode->OpCode == EFI_IFR_TIME_OP) {\r
+ InputWidth = 2;\r
+\r
+ if (MenuOption->Sequence == 0) {\r
+ InputText[0] = LEFT_NUMERIC_DELIMITER;\r
+ SetUnicodeMem (InputText + 1, InputWidth, L' ');\r
+ } else {\r
+ SetUnicodeMem (InputText, InputWidth, L' ');\r
+ }\r
+\r
+ if (MenuOption->Sequence == 2) {\r
+ InputText[InputWidth + 1] = RIGHT_NUMERIC_DELIMITER;\r
+ } else {\r
+ InputText[InputWidth + 1] = TIME_SEPARATOR;\r
+ }\r
+ InputText[InputWidth + 2] = L'\0';\r
+\r
+ PrintStringAt (Column, Row, InputText);\r
+ if (MenuOption->Sequence == 0) {\r
+ Column++;\r
+ }\r
+ }\r
+ }\r
+\r
+ //\r
+ // First time we enter this handler, we need to check to see if\r
+ // we were passed an increment or decrement directive\r
+ //\r
+ do {\r
+ Key.UnicodeChar = CHAR_NULL;\r
+ if (gDirection != 0) {\r
+ Key.ScanCode = gDirection;\r
+ gDirection = 0;\r
+ goto TheKey2;\r
+ }\r
+\r
+ Status = WaitForKeyStroke (&Key);\r
+\r
+TheKey2:\r
+ switch (Key.UnicodeChar) {\r
+\r
+ case '+':\r
+ case '-':\r
+ if (Key.UnicodeChar == '+') {\r
+ Key.ScanCode = SCAN_RIGHT;\r
+ } else {\r
+ Key.ScanCode = SCAN_LEFT;\r
+ }\r
+ Key.UnicodeChar = CHAR_NULL;\r
+ goto TheKey2;\r
+\r
+ case CHAR_NULL:\r
+ switch (Key.ScanCode) {\r
+ case SCAN_LEFT:\r
+ case SCAN_RIGHT:\r
+ if (DateOrTime && !ManualInput) {\r
+ //\r
+ // By setting this value, we will return back to the caller.\r
+ // We need to do this since an auto-refresh will destroy the adjustment\r
+ // based on what the real-time-clock is showing. So we always commit\r
+ // upon changing the value.\r
+ //\r
+ gDirection = SCAN_DOWN;\r
+ }\r
+\r
+ if ((Step != 0) && !ManualInput) {\r
+ if (Key.ScanCode == SCAN_LEFT) {\r
+ if (EditValue >= Minimum + Step) {\r
+ EditValue = EditValue - Step;\r
+ } else if (EditValue > Minimum){\r
+ EditValue = Minimum;\r
+ } else {\r
+ EditValue = Maximum;\r
+ }\r
+ } else if (Key.ScanCode == SCAN_RIGHT) {\r
+ if (EditValue + Step <= Maximum) {\r
+ EditValue = EditValue + Step;\r
+ } else if (EditValue < Maximum) {\r
+ EditValue = Maximum;\r
+ } else {\r
+ EditValue = Minimum;\r
+ }\r
+ }\r
+\r
+ ZeroMem (FormattedNumber, 21 * sizeof (CHAR16));\r
+ if (Question->OpCode->OpCode == EFI_IFR_DATE_OP) {\r
+ if (MenuOption->Sequence == 2) {\r
+ //\r
+ // Year\r
+ //\r
+ UnicodeSPrint (FormattedNumber, 21 * sizeof (CHAR16), L"%04d", (UINT16) EditValue);\r
+ } else {\r
+ //\r
+ // Month/Day\r
+ //\r
+ UnicodeSPrint (FormattedNumber, 21 * sizeof (CHAR16), L"%02d", (UINT8) EditValue);\r
+ }\r
+\r
+ if (MenuOption->Sequence == 0) {\r
+ ASSERT (EraseLen >= 2);\r
+ FormattedNumber[EraseLen - 2] = DATE_SEPARATOR;\r
+ } else if (MenuOption->Sequence == 1) {\r
+ ASSERT (EraseLen >= 1);\r
+ FormattedNumber[EraseLen - 1] = DATE_SEPARATOR;\r
+ }\r
+ } else if (Question->OpCode->OpCode == EFI_IFR_TIME_OP) {\r
+ UnicodeSPrint (FormattedNumber, 21 * sizeof (CHAR16), L"%02d", (UINT8) EditValue);\r
+\r
+ if (MenuOption->Sequence == 0) {\r
+ ASSERT (EraseLen >= 2);\r
+ FormattedNumber[EraseLen - 2] = TIME_SEPARATOR;\r
+ } else if (MenuOption->Sequence == 1) {\r
+ ASSERT (EraseLen >= 1);\r
+ FormattedNumber[EraseLen - 1] = TIME_SEPARATOR;\r
+ }\r
+ } else {\r
+ QuestionValue->Value.u64 = EditValue;\r
+ PrintFormattedNumber (Question, FormattedNumber, 21 * sizeof (CHAR16));\r
+ }\r
+\r
+ gST->ConOut->SetAttribute (gST->ConOut, GetFieldTextColor ());\r
+ for (Loop = 0; Loop < EraseLen; Loop++) {\r
+ PrintStringAt (MenuOption->OptCol + Loop, MenuOption->Row, L" ");\r
+ }\r
+ gST->ConOut->SetAttribute (gST->ConOut, GetHighlightTextColor ());\r
+\r
+ if (MenuOption->Sequence == 0) {\r
+ PrintCharAt (MenuOption->OptCol, Row, LEFT_NUMERIC_DELIMITER);\r
+ Column = MenuOption->OptCol + 1;\r
+ }\r
+\r
+ PrintStringAt (Column, Row, FormattedNumber);\r
+\r
+ if (!DateOrTime || MenuOption->Sequence == 2) {\r
+ PrintCharAt ((UINTN)-1, (UINTN)-1, RIGHT_NUMERIC_DELIMITER);\r
+ }\r
+ }\r
+\r
+ goto EnterCarriageReturn;\r
+ break;\r
+\r
+ case SCAN_UP:\r
+ case SCAN_DOWN:\r
+ goto EnterCarriageReturn;\r
+\r
+ case SCAN_ESC:\r
+ return EFI_DEVICE_ERROR;\r
+\r
+ default:\r
+ break;\r
+ }\r
+\r
+ break;\r
+\r
+EnterCarriageReturn:\r
+\r
+ case CHAR_CARRIAGE_RETURN:\r
+ //\r
+ // Validate input value with Minimum value.\r
+ //\r
+ if (EditValue < Minimum) {\r
+ UpdateStatusBar (INPUT_ERROR, TRUE);\r
+ break;\r
+ } else {\r
+ UpdateStatusBar (INPUT_ERROR, FALSE);\r
+ }\r
+ \r
+ CopyMem (&gUserInput->InputValue, &Question->CurrentValue, sizeof (EFI_HII_VALUE));\r
+ QuestionValue = &gUserInput->InputValue;\r
+ //\r
+ // Store Edit value back to Question\r
+ //\r
+ if (Question->OpCode->OpCode == EFI_IFR_DATE_OP) {\r
+ switch (MenuOption->Sequence) {\r
+ case 0:\r
+ QuestionValue->Value.date.Month = (UINT8) EditValue;\r
+ break;\r
+\r
+ case 1:\r
+ QuestionValue->Value.date.Day = (UINT8) EditValue;\r
+ break;\r
+\r
+ case 2:\r
+ QuestionValue->Value.date.Year = (UINT16) EditValue;\r
+ break;\r
+\r
+ default:\r
+ break;\r
+ }\r
+ } else if (Question->OpCode->OpCode == EFI_IFR_TIME_OP) {\r
+ switch (MenuOption->Sequence) {\r
+ case 0:\r
+ QuestionValue->Value.time.Hour = (UINT8) EditValue;\r
+ break;\r
+\r
+ case 1:\r
+ QuestionValue->Value.time.Minute = (UINT8) EditValue;\r
+ break;\r
+\r
+ case 2:\r
+ QuestionValue->Value.time.Second = (UINT8) EditValue;\r
+ break;\r
+\r
+ default:\r
+ break;\r
+ }\r
+ } else {\r
+ //\r
+ // Numeric\r
+ //\r
+ QuestionValue->Value.u64 = EditValue;\r
+ }\r
+\r
+ //\r
+ // Adjust the value to the correct one.\r
+ // Sample like: 2012.02.29 -> 2013.02.29 -> 2013.02.01\r
+ // 2013.03.29 -> 2013.02.29 -> 2013.02.28\r
+ //\r
+ if (Question->OpCode->OpCode == EFI_IFR_DATE_OP && \r
+ (MenuOption->Sequence == 0 || MenuOption->Sequence == 2)) {\r
+ AdjustQuestionValue (QuestionValue, (UINT8)MenuOption->Sequence);\r
+ }\r
+\r
+ return ValidateQuestion (Question);\r
+ break;\r
+\r
+ case CHAR_BACKSPACE:\r
+ if (ManualInput) {\r
+ if (Count == 0) {\r
+ break;\r
+ }\r
+ //\r
+ // Remove a character\r
+ //\r
+ EditValue = PreviousNumber[Count - 1];\r
+ UpdateStatusBar (INPUT_ERROR, FALSE);\r
+ Count--;\r
+ Column--;\r
+ PrintStringAt (Column, Row, L" ");\r
+ }\r
+ break;\r
+\r
+ default:\r
+ if (ManualInput) {\r
+ if (HexInput) {\r
+ if ((Key.UnicodeChar >= L'0') && (Key.UnicodeChar <= L'9')) {\r
+ Digital = (UINT8) (Key.UnicodeChar - L'0');\r
+ } else if ((Key.UnicodeChar >= L'A') && (Key.UnicodeChar <= L'F')) {\r
+ Digital = (UINT8) (Key.UnicodeChar - L'A' + 0x0A);\r
+ } else if ((Key.UnicodeChar >= L'a') && (Key.UnicodeChar <= L'f')) {\r
+ Digital = (UINT8) (Key.UnicodeChar - L'a' + 0x0A);\r
+ } else {\r
+ UpdateStatusBar (INPUT_ERROR, TRUE);\r
+ break;\r
+ }\r
+ } else {\r
+ if (Key.UnicodeChar > L'9' || Key.UnicodeChar < L'0') {\r
+ UpdateStatusBar (INPUT_ERROR, TRUE);\r
+ break;\r
+ }\r
+ }\r
+\r
+ //\r
+ // If Count exceed input width, there is no way more is valid\r
+ //\r
+ if (Count >= InputWidth) {\r
+ break;\r
+ }\r
+ //\r
+ // Someone typed something valid!\r
+ //\r
+ if (Count != 0) {\r
+ if (HexInput) {\r
+ EditValue = LShiftU64 (EditValue, 4) + Digital;\r
+ } else {\r
+ EditValue = MultU64x32 (EditValue, 10) + (Key.UnicodeChar - L'0');\r
+ }\r
+ } else {\r
+ if (HexInput) {\r
+ EditValue = Digital;\r
+ } else {\r
+ EditValue = Key.UnicodeChar - L'0';\r
+ }\r
+ }\r
+\r
+ if (EditValue > Maximum) {\r
+ UpdateStatusBar (INPUT_ERROR, TRUE);\r
+ ASSERT (Count < sizeof (PreviousNumber) / sizeof (PreviousNumber[0]));\r
+ EditValue = PreviousNumber[Count];\r
+ break;\r
+ } else {\r
+ UpdateStatusBar (INPUT_ERROR, FALSE);\r
+ }\r
+\r
+ Count++;\r
+ ASSERT (Count < (sizeof (PreviousNumber) / sizeof (PreviousNumber[0])));\r
+ PreviousNumber[Count] = EditValue;\r
+\r
+ gST->ConOut->SetAttribute (gST->ConOut, GetHighlightTextColor ());\r
+ PrintCharAt (Column, Row, Key.UnicodeChar);\r
+ Column++;\r
+ }\r
+ break;\r
+ }\r
+ } while (TRUE);\r
+}\r
+\r
+/**\r
+ Adjust option order base on the question value.\r
+\r
+ @param Question Pointer to current question.\r
+ @param PopUpMenuLines The line number of the pop up menu.\r
+\r
+ @retval EFI_SUCCESS If Option input is processed successfully\r
+ @retval EFI_DEVICE_ERROR If operation fails\r
+\r
+**/\r
+EFI_STATUS\r
+AdjustOptionOrder (\r
+ IN FORM_DISPLAY_ENGINE_STATEMENT *Question,\r
+ OUT UINTN *PopUpMenuLines\r
+ )\r
+{\r
+ UINTN Index;\r
+ EFI_IFR_ORDERED_LIST *OrderList;\r
+ UINT8 *ValueArray;\r
+ UINT8 ValueType;\r
+ LIST_ENTRY *Link;\r
+ DISPLAY_QUESTION_OPTION *OneOfOption;\r
+ EFI_HII_VALUE *HiiValueArray;\r
+\r
+ Link = GetFirstNode (&Question->OptionListHead);\r
+ OneOfOption = DISPLAY_QUESTION_OPTION_FROM_LINK (Link);\r
+ ValueArray = Question->CurrentValue.Buffer;\r
+ ValueType = OneOfOption->OptionOpCode->Type;\r
+ OrderList = (EFI_IFR_ORDERED_LIST *) Question->OpCode;\r
+\r
+ for (Index = 0; Index < OrderList->MaxContainers; Index++) {\r
+ if (GetArrayData (ValueArray, ValueType, Index) == 0) {\r
+ break;\r
+ }\r
+ }\r
+ \r
+ *PopUpMenuLines = Index;\r
+ \r
+ //\r
+ // Prepare HiiValue array\r
+ // \r
+ HiiValueArray = AllocateZeroPool (*PopUpMenuLines * sizeof (EFI_HII_VALUE));\r
+ ASSERT (HiiValueArray != NULL);\r
+\r
+ for (Index = 0; Index < *PopUpMenuLines; Index++) {\r
+ HiiValueArray[Index].Type = ValueType;\r
+ HiiValueArray[Index].Value.u64 = GetArrayData (ValueArray, ValueType, Index);\r
+ }\r
+ \r
+ for (Index = 0; Index < *PopUpMenuLines; Index++) {\r
+ OneOfOption = ValueToOption (Question, &HiiValueArray[*PopUpMenuLines - Index - 1]);\r
+ if (OneOfOption == NULL) {\r
+ return EFI_NOT_FOUND;\r
+ }\r
+ \r
+ RemoveEntryList (&OneOfOption->Link);\r
+ \r
+ //\r
+ // Insert to head.\r
+ //\r
+ InsertHeadList (&Question->OptionListHead, &OneOfOption->Link);\r
+ }\r
+ \r
+ FreePool (HiiValueArray);\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+ Base on the type to compare the value.\r
+\r
+ @param Value1 The first value need to compare.\r
+ @param Value2 The second value need to compare.\r
+ @param Type The value type for above two values.\r
+\r
+ @retval TRUE The two value are same.\r
+ @retval FALSE The two value are different.\r
+\r
+**/\r
+BOOLEAN\r
+IsValuesEqual (\r
+ IN EFI_IFR_TYPE_VALUE *Value1,\r
+ IN EFI_IFR_TYPE_VALUE *Value2,\r
+ IN UINT8 Type\r
+ )\r
+{\r
+ switch (Type) {\r
+ case EFI_IFR_TYPE_BOOLEAN:\r
+ case EFI_IFR_TYPE_NUM_SIZE_8:\r
+ return (BOOLEAN) (Value1->u8 == Value2->u8);\r
+ \r
+ case EFI_IFR_TYPE_NUM_SIZE_16:\r
+ return (BOOLEAN) (Value1->u16 == Value2->u16);\r
+ \r
+ case EFI_IFR_TYPE_NUM_SIZE_32:\r
+ return (BOOLEAN) (Value1->u32 == Value2->u32);\r
+ \r
+ case EFI_IFR_TYPE_NUM_SIZE_64:\r
+ return (BOOLEAN) (Value1->u64 == Value2->u64);\r
+\r
+ default:\r
+ ASSERT (FALSE);\r
+ return FALSE;\r
+ }\r
+}\r
+\r
+/**\r
+ Base on the type to set the value.\r
+\r
+ @param Dest The dest value.\r
+ @param Source The source value.\r
+ @param Type The value type for above two values.\r
+\r
+**/\r
+VOID\r
+SetValuesByType (\r
+ OUT EFI_IFR_TYPE_VALUE *Dest,\r
+ IN EFI_IFR_TYPE_VALUE *Source,\r
+ IN UINT8 Type\r
+ )\r
+{\r
+ switch (Type) {\r
+ case EFI_IFR_TYPE_BOOLEAN:\r
+ Dest->b = Source->b;\r
+ break;\r
+\r
+ case EFI_IFR_TYPE_NUM_SIZE_8:\r
+ Dest->u8 = Source->u8;\r
+ break;\r
+\r
+ case EFI_IFR_TYPE_NUM_SIZE_16:\r
+ Dest->u16 = Source->u16;\r
+ break;\r
+\r
+ case EFI_IFR_TYPE_NUM_SIZE_32:\r
+ Dest->u32 = Source->u32;\r
+ break;\r
+\r
+ case EFI_IFR_TYPE_NUM_SIZE_64:\r
+ Dest->u64 = Source->u64;\r
+ break;\r
+\r
+ default:\r
+ ASSERT (FALSE);\r
+ break;\r
+ }\r
+}\r
+\r
+/**\r
+ Get selection for OneOf and OrderedList (Left/Right will be ignored).\r
+\r
+ @param MenuOption Pointer to the current input menu.\r
+\r
+ @retval EFI_SUCCESS If Option input is processed successfully\r
+ @retval EFI_DEVICE_ERROR If operation fails\r
+\r
+**/\r
+EFI_STATUS\r
+GetSelectionInputPopUp (\r
+ IN UI_MENU_OPTION *MenuOption\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ EFI_INPUT_KEY Key;\r
+ UINTN Index;\r
+ CHAR16 *StringPtr;\r
+ CHAR16 *TempStringPtr;\r
+ UINTN Index2;\r
+ UINTN TopOptionIndex;\r
+ UINTN HighlightOptionIndex;\r
+ UINTN Start;\r
+ UINTN End;\r
+ UINTN Top;\r
+ UINTN Bottom;\r
+ UINTN PopUpMenuLines;\r
+ UINTN MenuLinesInView;\r
+ UINTN PopUpWidth;\r
+ CHAR16 Character;\r
+ INT32 SavedAttribute;\r
+ BOOLEAN ShowDownArrow;\r
+ BOOLEAN ShowUpArrow;\r
+ UINTN DimensionsWidth;\r
+ LIST_ENTRY *Link;\r
+ BOOLEAN OrderedList;\r
+ UINT8 *ValueArray;\r
+ UINT8 *ReturnValue;\r
+ UINT8 ValueType;\r
+ EFI_HII_VALUE HiiValue;\r
+ DISPLAY_QUESTION_OPTION *OneOfOption;\r
+ DISPLAY_QUESTION_OPTION *CurrentOption;\r
+ FORM_DISPLAY_ENGINE_STATEMENT *Question;\r
+ INTN Result;\r
+ EFI_IFR_ORDERED_LIST *OrderList;\r
+\r
+ DimensionsWidth = gStatementDimensions.RightColumn - gStatementDimensions.LeftColumn;\r
+\r
+ ValueArray = NULL;\r
+ ValueType = 0;\r
+ CurrentOption = NULL;\r
+ ShowDownArrow = FALSE;\r
+ ShowUpArrow = FALSE;\r
+\r
+ StringPtr = AllocateZeroPool ((gOptionBlockWidth + 1) * 2);\r
+ ASSERT (StringPtr);\r
+\r
+ ZeroMem (&HiiValue, sizeof (EFI_HII_VALUE));\r
+\r
+ Question = MenuOption->ThisTag;\r
+ if (Question->OpCode->OpCode == EFI_IFR_ORDERED_LIST_OP) {\r
+ Link = GetFirstNode (&Question->OptionListHead);\r
+ OneOfOption = DISPLAY_QUESTION_OPTION_FROM_LINK (Link);\r
+ ValueArray = Question->CurrentValue.Buffer;\r
+ ValueType = OneOfOption->OptionOpCode->Type;\r
+ OrderedList = TRUE;\r
+ OrderList = (EFI_IFR_ORDERED_LIST *) Question->OpCode;\r
+ } else {\r
+ OrderedList = FALSE;\r
+ OrderList = NULL;\r
+ }\r
+\r
+ //\r
+ // Calculate Option count\r
+ //\r
+ PopUpMenuLines = 0;\r
+ if (OrderedList) {\r
+ AdjustOptionOrder(Question, &PopUpMenuLines);\r
+ } else {\r
+ Link = GetFirstNode (&Question->OptionListHead);\r
+ while (!IsNull (&Question->OptionListHead, Link)) {\r
+ OneOfOption = DISPLAY_QUESTION_OPTION_FROM_LINK (Link);\r
+ PopUpMenuLines++;\r
+ Link = GetNextNode (&Question->OptionListHead, Link);\r
+ }\r
+ }\r
+\r
+ //\r
+ // Get the number of one of options present and its size\r
+ //\r
+ PopUpWidth = 0;\r
+ HighlightOptionIndex = 0;\r
+ Link = GetFirstNode (&Question->OptionListHead);\r
+ for (Index = 0; Index < PopUpMenuLines; Index++) {\r
+ OneOfOption = DISPLAY_QUESTION_OPTION_FROM_LINK (Link);\r
+\r
+ StringPtr = GetToken (OneOfOption->OptionOpCode->Option, gFormData->HiiHandle);\r
+ if (StrLen (StringPtr) > PopUpWidth) {\r
+ PopUpWidth = StrLen (StringPtr);\r
+ }\r
+ FreePool (StringPtr);\r
+ HiiValue.Type = OneOfOption->OptionOpCode->Type;\r
+ SetValuesByType (&HiiValue.Value, &OneOfOption->OptionOpCode->Value, HiiValue.Type);\r
+ if (!OrderedList && (CompareHiiValue (&Question->CurrentValue, &HiiValue, &Result, NULL) == EFI_SUCCESS) && (Result == 0)) {\r
+ //\r
+ // Find current selected Option for OneOf\r
+ //\r
+ HighlightOptionIndex = Index;\r
+ }\r
+\r
+ Link = GetNextNode (&Question->OptionListHead, Link);\r
+ }\r
+\r
+ //\r
+ // Perform popup menu initialization.\r
+ //\r
+ PopUpWidth = PopUpWidth + POPUP_PAD_SPACE_COUNT;\r
+\r
+ SavedAttribute = gST->ConOut->Mode->Attribute;\r
+ gST->ConOut->SetAttribute (gST->ConOut, GetPopupColor ());\r
+\r
+ if ((PopUpWidth + POPUP_FRAME_WIDTH) > DimensionsWidth) {\r
+ PopUpWidth = DimensionsWidth - POPUP_FRAME_WIDTH;\r
+ }\r
+\r
+ Start = (DimensionsWidth - PopUpWidth - POPUP_FRAME_WIDTH) / 2 + gStatementDimensions.LeftColumn;\r
+ End = Start + PopUpWidth + POPUP_FRAME_WIDTH;\r
+ Top = gStatementDimensions.TopRow;\r
+ Bottom = gStatementDimensions.BottomRow - 1;\r
+\r
+ MenuLinesInView = Bottom - Top - 1;\r
+ if (MenuLinesInView >= PopUpMenuLines) {\r
+ Top = Top + (MenuLinesInView - PopUpMenuLines) / 2;\r
+ Bottom = Top + PopUpMenuLines + 1;\r
+ } else {\r
+ ShowDownArrow = TRUE;\r
+ }\r
+\r
+ if (HighlightOptionIndex > (MenuLinesInView - 1)) {\r
+ TopOptionIndex = HighlightOptionIndex - MenuLinesInView + 1;\r
+ } else {\r
+ TopOptionIndex = 0;\r
+ }\r
+\r
+ do {\r
+ //\r
+ // Clear that portion of the screen\r
+ //\r
+ ClearLines (Start, End, Top, Bottom, GetPopupColor ());\r
+\r
+ //\r
+ // Draw "One of" pop-up menu\r
+ //\r
+ Character = BOXDRAW_DOWN_RIGHT;\r
+ PrintCharAt (Start, Top, Character);\r
+ for (Index = Start; Index + 2 < End; Index++) {\r
+ if ((ShowUpArrow) && ((Index + 1) == (Start + End) / 2)) {\r
+ Character = GEOMETRICSHAPE_UP_TRIANGLE;\r
+ } else {\r
+ Character = BOXDRAW_HORIZONTAL;\r
+ }\r
+\r
+ PrintCharAt ((UINTN)-1, (UINTN)-1, Character);\r
+ }\r
+\r
+ Character = BOXDRAW_DOWN_LEFT;\r
+ PrintCharAt ((UINTN)-1, (UINTN)-1, Character);\r
+ Character = BOXDRAW_VERTICAL;\r
+ for (Index = Top + 1; Index < Bottom; Index++) {\r
+ PrintCharAt (Start, Index, Character);\r
+ PrintCharAt (End - 1, Index, Character);\r
+ }\r
+\r
+ //\r
+ // Move to top Option\r
+ //\r
+ Link = GetFirstNode (&Question->OptionListHead);\r
+ for (Index = 0; Index < TopOptionIndex; Index++) {\r
+ Link = GetNextNode (&Question->OptionListHead, Link);\r
+ }\r
+\r
+ //\r
+ // Display the One of options\r
+ //\r
+ Index2 = Top + 1;\r
+ for (Index = TopOptionIndex; (Index < PopUpMenuLines) && (Index2 < Bottom); Index++) {\r
+ OneOfOption = DISPLAY_QUESTION_OPTION_FROM_LINK (Link);\r
+ Link = GetNextNode (&Question->OptionListHead, Link);\r
+\r
+ StringPtr = GetToken (OneOfOption->OptionOpCode->Option, gFormData->HiiHandle);\r
+ ASSERT (StringPtr != NULL);\r
+ //\r
+ // If the string occupies multiple lines, truncate it to fit in one line,\r
+ // and append a "..." for indication.\r
+ //\r
+ if (StrLen (StringPtr) > (PopUpWidth - 1)) {\r
+ TempStringPtr = AllocateZeroPool (sizeof (CHAR16) * (PopUpWidth - 1));\r
+ ASSERT ( TempStringPtr != NULL );\r
+ CopyMem (TempStringPtr, StringPtr, (sizeof (CHAR16) * (PopUpWidth - 5)));\r
+ FreePool (StringPtr);\r
+ StringPtr = TempStringPtr;\r
+ StrCat (StringPtr, L"...");\r
+ }\r
+\r
+ if (Index == HighlightOptionIndex) {\r
+ //\r
+ // Highlight the selected one\r
+ //\r
+ CurrentOption = OneOfOption;\r
+\r
+ gST->ConOut->SetAttribute (gST->ConOut, GetPickListColor ());\r
+ PrintStringAt (Start + 2, Index2, StringPtr);\r
+ gST->ConOut->SetAttribute (gST->ConOut, GetPopupColor ());\r
+ } else {\r
+ gST->ConOut->SetAttribute (gST->ConOut, GetPopupColor ());\r
+ PrintStringAt (Start + 2, Index2, StringPtr);\r
+ }\r
+\r
+ Index2++;\r
+ FreePool (StringPtr);\r
+ }\r
+\r
+ Character = BOXDRAW_UP_RIGHT;\r
+ PrintCharAt (Start, Bottom, Character);\r
+ for (Index = Start; Index + 2 < End; Index++) {\r
+ if ((ShowDownArrow) && ((Index + 1) == (Start + End) / 2)) {\r
+ Character = GEOMETRICSHAPE_DOWN_TRIANGLE;\r
+ } else {\r
+ Character = BOXDRAW_HORIZONTAL;\r
+ }\r
+\r
+ PrintCharAt ((UINTN)-1, (UINTN)-1, Character);\r
+ }\r
+\r
+ Character = BOXDRAW_UP_LEFT;\r
+ PrintCharAt ((UINTN)-1, (UINTN)-1, Character);\r
+\r
+ //\r
+ // Get User selection\r
+ //\r
+ Key.UnicodeChar = CHAR_NULL;\r
+ if ((gDirection == SCAN_UP) || (gDirection == SCAN_DOWN)) {\r
+ Key.ScanCode = gDirection;\r
+ gDirection = 0;\r
+ goto TheKey;\r
+ }\r
+\r
+ Status = WaitForKeyStroke (&Key);\r
+\r
+TheKey:\r
+ switch (Key.UnicodeChar) {\r
+ case '+':\r
+ if (OrderedList) {\r
+ if ((TopOptionIndex > 0) && (TopOptionIndex == HighlightOptionIndex)) {\r
+ //\r
+ // Highlight reaches the top of the popup window, scroll one menu item.\r
+ //\r
+ TopOptionIndex--;\r
+ ShowDownArrow = TRUE;\r
+ }\r
+\r
+ if (TopOptionIndex == 0) {\r
+ ShowUpArrow = FALSE;\r
+ }\r
+\r
+ if (HighlightOptionIndex > 0) {\r
+ HighlightOptionIndex--;\r
+\r
+ ASSERT (CurrentOption != NULL);\r
+ SwapListEntries (CurrentOption->Link.BackLink, &CurrentOption->Link);\r
+ }\r
+ }\r
+ break;\r
+\r
+ case '-':\r
+ //\r
+ // If an ordered list op-code, we will allow for a popup of +/- keys\r
+ // to create an ordered list of items\r
+ //\r
+ if (OrderedList) {\r
+ if (((TopOptionIndex + MenuLinesInView) < PopUpMenuLines) &&\r
+ (HighlightOptionIndex == (TopOptionIndex + MenuLinesInView - 1))) {\r
+ //\r
+ // Highlight reaches the bottom of the popup window, scroll one menu item.\r
+ //\r
+ TopOptionIndex++;\r
+ ShowUpArrow = TRUE;\r
+ }\r
+\r
+ if ((TopOptionIndex + MenuLinesInView) == PopUpMenuLines) {\r
+ ShowDownArrow = FALSE;\r
+ }\r
+\r
+ if (HighlightOptionIndex < (PopUpMenuLines - 1)) {\r
+ HighlightOptionIndex++;\r
+\r
+ ASSERT (CurrentOption != NULL);\r
+ SwapListEntries (&CurrentOption->Link, CurrentOption->Link.ForwardLink);\r
+ }\r
+ }\r
+ break;\r
+\r
+ case CHAR_NULL:\r
+ switch (Key.ScanCode) {\r
+ case SCAN_UP:\r
+ case SCAN_DOWN:\r
+ if (Key.ScanCode == SCAN_UP) {\r
+ if ((TopOptionIndex > 0) && (TopOptionIndex == HighlightOptionIndex)) {\r
+ //\r
+ // Highlight reaches the top of the popup window, scroll one menu item.\r
+ //\r
+ TopOptionIndex--;\r
+ ShowDownArrow = TRUE;\r
+ }\r
+\r
+ if (TopOptionIndex == 0) {\r
+ ShowUpArrow = FALSE;\r
+ }\r
+\r
+ if (HighlightOptionIndex > 0) {\r
+ HighlightOptionIndex--;\r
+ }\r
+ } else {\r
+ if (((TopOptionIndex + MenuLinesInView) < PopUpMenuLines) &&\r
+ (HighlightOptionIndex == (TopOptionIndex + MenuLinesInView - 1))) {\r
+ //\r
+ // Highlight reaches the bottom of the popup window, scroll one menu item.\r
+ //\r
+ TopOptionIndex++;\r
+ ShowUpArrow = TRUE;\r
+ }\r
+\r
+ if ((TopOptionIndex + MenuLinesInView) == PopUpMenuLines) {\r
+ ShowDownArrow = FALSE;\r
+ }\r
+\r
+ if (HighlightOptionIndex < (PopUpMenuLines - 1)) {\r
+ HighlightOptionIndex++;\r
+ }\r
+ }\r
+ break;\r
+\r
+ case SCAN_ESC:\r
+ gST->ConOut->SetAttribute (gST->ConOut, SavedAttribute);\r
+\r
+ //\r
+ // Restore link list order for orderedlist\r
+ //\r
+ if (OrderedList) {\r
+ HiiValue.Type = ValueType;\r
+ HiiValue.Value.u64 = 0;\r
+ for (Index = 0; Index < OrderList->MaxContainers; Index++) {\r
+ HiiValue.Value.u64 = GetArrayData (ValueArray, ValueType, Index);\r
+ if (HiiValue.Value.u64 == 0) {\r
+ break;\r
+ }\r
+\r
+ OneOfOption = ValueToOption (Question, &HiiValue);\r
+ if (OneOfOption == NULL) {\r
+ return EFI_NOT_FOUND;\r
+ }\r
+\r
+ RemoveEntryList (&OneOfOption->Link);\r
+ InsertTailList (&Question->OptionListHead, &OneOfOption->Link);\r
+ }\r
+ }\r
+\r
+ return EFI_DEVICE_ERROR;\r
+\r
+ default:\r
+ break;\r
+ }\r
+\r
+ break;\r
+\r
+ case CHAR_CARRIAGE_RETURN:\r
+ //\r
+ // return the current selection\r
+ //\r
+ if (OrderedList) {\r
+ ReturnValue = AllocateZeroPool (Question->CurrentValue.BufferLen);\r
+ ASSERT (ReturnValue != NULL);\r
+ Index = 0;\r
+ Link = GetFirstNode (&Question->OptionListHead);\r
+ while (!IsNull (&Question->OptionListHead, Link)) {\r
+ OneOfOption = DISPLAY_QUESTION_OPTION_FROM_LINK (Link);\r
+ Link = GetNextNode (&Question->OptionListHead, Link);\r
+\r
+ SetArrayData (ReturnValue, ValueType, Index, OneOfOption->OptionOpCode->Value.u64);\r
+\r
+ Index++;\r
+ if (Index > OrderList->MaxContainers) {\r
+ break;\r
+ }\r
+ }\r
+ if (CompareMem (ReturnValue, ValueArray, Question->CurrentValue.BufferLen) == 0) {\r
+ FreePool (ReturnValue);\r
+ return EFI_DEVICE_ERROR;\r
+ } else {\r
+ gUserInput->InputValue.Buffer = ReturnValue;\r
+ gUserInput->InputValue.BufferLen = Question->CurrentValue.BufferLen;\r
+ Status = EFI_SUCCESS;\r
+ }\r
+ } else {\r
+ ASSERT (CurrentOption != NULL);\r
+ gUserInput->InputValue.Type = CurrentOption->OptionOpCode->Type;\r
+ if (IsValuesEqual (&Question->CurrentValue.Value, &CurrentOption->OptionOpCode->Value, gUserInput->InputValue.Type)) {\r
+ return EFI_DEVICE_ERROR;\r
+ } else {\r
+ SetValuesByType (&gUserInput->InputValue.Value, &CurrentOption->OptionOpCode->Value, gUserInput->InputValue.Type);\r
+ Status = EFI_SUCCESS;\r
+ }\r
+ }\r
+\r
+ gST->ConOut->SetAttribute (gST->ConOut, SavedAttribute);\r
+\r
+ return ValidateQuestion (Question);\r
+ \r
+ default:\r
+ break;\r
+ }\r
+ } while (TRUE);\r
+\r
+}\r
+\r
--- /dev/null
+/** @file\r
+Implementation for handling the User Interface option processing.\r
+\r
+\r
+Copyright (c) 2004 - 2012, 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
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#include "FormDisplay.h"\r
+\r
+/**\r
+ Concatenate a narrow string to another string.\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
+\r
+**/\r
+VOID\r
+NewStrCat (\r
+ IN OUT CHAR16 *Destination,\r
+ IN CHAR16 *Source\r
+ )\r
+{\r
+ UINTN Length;\r
+\r
+ for (Length = 0; Destination[Length] != 0; Length++)\r
+ ;\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
+ //\r
+ Destination[Length] = NARROW_CHAR;\r
+ Length++;\r
+\r
+ StrCpy (Destination + Length, Source);\r
+}\r
+\r
+/**\r
+ Compare two Hii value.\r
+\r
+ @param Value1 Expression value to compare on left-hand.\r
+ @param Value2 Expression value to compare on right-hand.\r
+ @param Result Return value after compare.\r
+ retval 0 Two operators equal.\r
+ return Positive value if Value1 is greater than Value2.\r
+ retval Negative value if Value1 is less than Value2.\r
+ @param HiiHandle Only required for string compare.\r
+\r
+ @retval other Could not perform compare on two values.\r
+ @retval EFI_SUCCESS Compare the value success.\r
+\r
+**/\r
+EFI_STATUS\r
+CompareHiiValue (\r
+ IN EFI_HII_VALUE *Value1,\r
+ IN EFI_HII_VALUE *Value2,\r
+ OUT INTN *Result,\r
+ IN EFI_HII_HANDLE HiiHandle OPTIONAL\r
+ )\r
+{\r
+ INT64 Temp64;\r
+ CHAR16 *Str1;\r
+ CHAR16 *Str2;\r
+ UINTN Len;\r
+\r
+ if (Value1->Type >= EFI_IFR_TYPE_OTHER || Value2->Type >= EFI_IFR_TYPE_OTHER ) {\r
+ if (Value1->Type != EFI_IFR_TYPE_BUFFER && Value2->Type != EFI_IFR_TYPE_BUFFER) {\r
+ return EFI_UNSUPPORTED;\r
+ }\r
+ }\r
+\r
+ if (Value1->Type == EFI_IFR_TYPE_STRING || Value2->Type == EFI_IFR_TYPE_STRING ) {\r
+ if (Value1->Type != Value2->Type) {\r
+ //\r
+ // Both Operator should be type of String\r
+ //\r
+ return EFI_UNSUPPORTED;\r
+ }\r
+\r
+ if (Value1->Value.string == 0 || Value2->Value.string == 0) {\r
+ //\r
+ // StringId 0 is reserved\r
+ //\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ if (Value1->Value.string == Value2->Value.string) {\r
+ *Result = 0;\r
+ return EFI_SUCCESS;\r
+ }\r
+\r
+ Str1 = GetToken (Value1->Value.string, HiiHandle);\r
+ if (Str1 == NULL) {\r
+ //\r
+ // String not found\r
+ //\r
+ return EFI_NOT_FOUND;\r
+ }\r
+\r
+ Str2 = GetToken (Value2->Value.string, HiiHandle);\r
+ if (Str2 == NULL) {\r
+ FreePool (Str1);\r
+ return EFI_NOT_FOUND;\r
+ }\r
+\r
+ *Result = StrCmp (Str1, Str2);\r
+\r
+ FreePool (Str1);\r
+ FreePool (Str2);\r
+\r
+ return EFI_SUCCESS;\r
+ }\r
+\r
+ if (Value1->Type == EFI_IFR_TYPE_BUFFER || Value2->Type == EFI_IFR_TYPE_BUFFER ) {\r
+ if (Value1->Type != Value2->Type) {\r
+ //\r
+ // Both Operator should be type of Buffer.\r
+ //\r
+ return EFI_UNSUPPORTED;\r
+ }\r
+ Len = Value1->BufferLen > Value2->BufferLen ? Value2->BufferLen : Value1->BufferLen;\r
+ *Result = CompareMem (Value1->Buffer, Value2->Buffer, Len);\r
+ if ((*Result == 0) && (Value1->BufferLen != Value2->BufferLen))\r
+ {\r
+ //\r
+ // In this case, means base on samll number buffer, the data is same\r
+ // So which value has more data, which value is bigger.\r
+ //\r
+ *Result = Value1->BufferLen > Value2->BufferLen ? 1 : -1;\r
+ }\r
+ return EFI_SUCCESS;\r
+ } \r
+\r
+ //\r
+ // Take remain types(integer, boolean, date/time) as integer\r
+ //\r
+ Temp64 = (INT64) (Value1->Value.u64 - Value2->Value.u64);\r
+ if (Temp64 > 0) {\r
+ *Result = 1;\r
+ } else if (Temp64 < 0) {\r
+ *Result = -1;\r
+ } else {\r
+ *Result = 0;\r
+ }\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+ Search an Option of a Question by its value.\r
+\r
+ @param Question The Question\r
+ @param OptionValue Value for Option to be searched.\r
+\r
+ @retval Pointer Pointer to the found Option.\r
+ @retval NULL Option not found.\r
+\r
+**/\r
+DISPLAY_QUESTION_OPTION *\r
+ValueToOption (\r
+ IN FORM_DISPLAY_ENGINE_STATEMENT *Question,\r
+ IN EFI_HII_VALUE *OptionValue\r
+ )\r
+{\r
+ LIST_ENTRY *Link;\r
+ DISPLAY_QUESTION_OPTION *Option;\r
+ INTN Result;\r
+ EFI_HII_VALUE Value;\r
+\r
+ Link = GetFirstNode (&Question->OptionListHead);\r
+ while (!IsNull (&Question->OptionListHead, Link)) {\r
+ Option = DISPLAY_QUESTION_OPTION_FROM_LINK (Link);\r
+\r
+ ZeroMem (&Value, sizeof (EFI_HII_VALUE));\r
+ Value.Type = Option->OptionOpCode->Type;\r
+ CopyMem (&Value.Value, &Option->OptionOpCode->Value, Option->OptionOpCode->Header.Length - OFFSET_OF (EFI_IFR_ONE_OF_OPTION, Value));\r
+ \r
+ if ((CompareHiiValue (&Value, OptionValue, &Result, NULL) == EFI_SUCCESS) && (Result == 0)) {\r
+ return Option;\r
+ }\r
+\r
+ Link = GetNextNode (&Question->OptionListHead, Link);\r
+ }\r
+\r
+ return NULL;\r
+}\r
+\r
+\r
+/**\r
+ Return data element in an Array by its Index.\r
+\r
+ @param Array The data array.\r
+ @param Type Type of the data in this array.\r
+ @param Index Zero based index for data in this array.\r
+\r
+ @retval Value The data to be returned\r
+\r
+**/\r
+UINT64\r
+GetArrayData (\r
+ IN VOID *Array,\r
+ IN UINT8 Type,\r
+ IN UINTN Index\r
+ )\r
+{\r
+ UINT64 Data;\r
+\r
+ ASSERT (Array != NULL);\r
+\r
+ Data = 0;\r
+ switch (Type) {\r
+ case EFI_IFR_TYPE_NUM_SIZE_8:\r
+ Data = (UINT64) *(((UINT8 *) Array) + Index);\r
+ break;\r
+\r
+ case EFI_IFR_TYPE_NUM_SIZE_16:\r
+ Data = (UINT64) *(((UINT16 *) Array) + Index);\r
+ break;\r
+\r
+ case EFI_IFR_TYPE_NUM_SIZE_32:\r
+ Data = (UINT64) *(((UINT32 *) Array) + Index);\r
+ break;\r
+\r
+ case EFI_IFR_TYPE_NUM_SIZE_64:\r
+ Data = (UINT64) *(((UINT64 *) Array) + Index);\r
+ break;\r
+\r
+ default:\r
+ break;\r
+ }\r
+\r
+ return Data;\r
+}\r
+\r
+\r
+/**\r
+ Set value of a data element in an Array by its Index.\r
+\r
+ @param Array The data array.\r
+ @param Type Type of the data in this array.\r
+ @param Index Zero based index for data in this array.\r
+ @param Value The value to be set.\r
+\r
+**/\r
+VOID\r
+SetArrayData (\r
+ IN VOID *Array,\r
+ IN UINT8 Type,\r
+ IN UINTN Index,\r
+ IN UINT64 Value\r
+ )\r
+{\r
+\r
+ ASSERT (Array != NULL);\r
+\r
+ switch (Type) {\r
+ case EFI_IFR_TYPE_NUM_SIZE_8:\r
+ *(((UINT8 *) Array) + Index) = (UINT8) Value;\r
+ break;\r
+\r
+ case EFI_IFR_TYPE_NUM_SIZE_16:\r
+ *(((UINT16 *) Array) + Index) = (UINT16) Value;\r
+ break;\r
+\r
+ case EFI_IFR_TYPE_NUM_SIZE_32:\r
+ *(((UINT32 *) Array) + Index) = (UINT32) Value;\r
+ break;\r
+\r
+ case EFI_IFR_TYPE_NUM_SIZE_64:\r
+ *(((UINT64 *) Array) + Index) = (UINT64) Value;\r
+ break;\r
+\r
+ default:\r
+ break;\r
+ }\r
+}\r
+\r
+/**\r
+ Check whether this value already in the array, if yes, return the index.\r
+\r
+ @param Array The data array.\r
+ @param Type Type of the data in this array.\r
+ @param Value The value to be find.\r
+ @param Index The index in the array which has same value with Value.\r
+ \r
+ @retval TRUE Found the value in the array.\r
+ @retval FALSE Not found the value.\r
+\r
+**/\r
+BOOLEAN \r
+FindArrayData (\r
+ IN VOID *Array,\r
+ IN UINT8 Type,\r
+ IN UINT64 Value,\r
+ OUT UINTN *Index OPTIONAL\r
+ )\r
+{\r
+ UINTN Count;\r
+ UINT64 TmpValue;\r
+ UINT64 ValueComp;\r
+ \r
+ ASSERT (Array != NULL);\r
+\r
+ Count = 0;\r
+ TmpValue = 0;\r
+\r
+ switch (Type) {\r
+ case EFI_IFR_TYPE_NUM_SIZE_8:\r
+ ValueComp = (UINT8) Value;\r
+ break;\r
+\r
+ case EFI_IFR_TYPE_NUM_SIZE_16:\r
+ ValueComp = (UINT16) Value;\r
+ break;\r
+\r
+ case EFI_IFR_TYPE_NUM_SIZE_32:\r
+ ValueComp = (UINT32) Value;\r
+ break;\r
+\r
+ case EFI_IFR_TYPE_NUM_SIZE_64:\r
+ ValueComp = (UINT64) Value;\r
+ break;\r
+\r
+ default:\r
+ ValueComp = 0;\r
+ break;\r
+ }\r
+\r
+ while ((TmpValue = GetArrayData (Array, Type, Count)) != 0) {\r
+ if (ValueComp == TmpValue) {\r
+ if (Index != NULL) {\r
+ *Index = Count;\r
+ }\r
+ return TRUE;\r
+ }\r
+\r
+ Count ++;\r
+ }\r
+\r
+ return FALSE;\r
+}\r
+\r
+/**\r
+ Print Question Value according to it's storage width and display attributes.\r
+\r
+ @param Question The Question to be printed.\r
+ @param FormattedNumber Buffer for output string.\r
+ @param BufferSize The FormattedNumber buffer size in bytes.\r
+\r
+ @retval EFI_SUCCESS Print success.\r
+ @retval EFI_BUFFER_TOO_SMALL Buffer size is not enough for formatted number.\r
+\r
+**/\r
+EFI_STATUS\r
+PrintFormattedNumber (\r
+ IN FORM_DISPLAY_ENGINE_STATEMENT *Question,\r
+ IN OUT CHAR16 *FormattedNumber,\r
+ IN UINTN BufferSize\r
+ )\r
+{\r
+ INT64 Value;\r
+ CHAR16 *Format;\r
+ EFI_HII_VALUE *QuestionValue;\r
+ EFI_IFR_NUMERIC *NumericOp;\r
+\r
+ if (BufferSize < (21 * sizeof (CHAR16))) {\r
+ return EFI_BUFFER_TOO_SMALL;\r
+ }\r
+\r
+ QuestionValue = &Question->CurrentValue;\r
+ NumericOp = (EFI_IFR_NUMERIC *) Question->OpCode;\r
+\r
+ Value = (INT64) QuestionValue->Value.u64;\r
+ switch (NumericOp->Flags & EFI_IFR_DISPLAY) {\r
+ case EFI_IFR_DISPLAY_INT_DEC:\r
+ switch (QuestionValue->Type) {\r
+ case EFI_IFR_NUMERIC_SIZE_1:\r
+ Value = (INT64) ((INT8) QuestionValue->Value.u8);\r
+ break;\r
+\r
+ case EFI_IFR_NUMERIC_SIZE_2:\r
+ Value = (INT64) ((INT16) QuestionValue->Value.u16);\r
+ break;\r
+\r
+ case EFI_IFR_NUMERIC_SIZE_4:\r
+ Value = (INT64) ((INT32) QuestionValue->Value.u32);\r
+ break;\r
+\r
+ case EFI_IFR_NUMERIC_SIZE_8:\r
+ default:\r
+ break;\r
+ }\r
+\r
+ if (Value < 0) {\r
+ Value = -Value;\r
+ Format = L"-%ld";\r
+ } else {\r
+ Format = L"%ld";\r
+ }\r
+ break;\r
+\r
+ case EFI_IFR_DISPLAY_UINT_DEC:\r
+ Format = L"%ld";\r
+ break;\r
+\r
+ case EFI_IFR_DISPLAY_UINT_HEX:\r
+ Format = L"%lx";\r
+ break;\r
+\r
+ default:\r
+ return EFI_UNSUPPORTED;\r
+ break;\r
+ }\r
+\r
+ UnicodeSPrint (FormattedNumber, BufferSize, Format, Value);\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+\r
+/**\r
+ Draw a pop up windows based on the dimension, number of lines and\r
+ strings specified.\r
+\r
+ @param RequestedWidth The width of the pop-up.\r
+ @param NumberOfLines The number of lines.\r
+ @param Marker The variable argument list for the list of string to be printed.\r
+\r
+**/\r
+VOID\r
+CreateSharedPopUp (\r
+ IN UINTN RequestedWidth,\r
+ IN UINTN NumberOfLines,\r
+ IN VA_LIST Marker\r
+ )\r
+{\r
+ UINTN Index;\r
+ UINTN Count;\r
+ CHAR16 Character;\r
+ UINTN Start;\r
+ UINTN End;\r
+ UINTN Top;\r
+ UINTN Bottom;\r
+ CHAR16 *String;\r
+ UINTN DimensionsWidth;\r
+ UINTN DimensionsHeight;\r
+\r
+ DimensionsWidth = gStatementDimensions.RightColumn - gStatementDimensions.LeftColumn;\r
+ DimensionsHeight = gStatementDimensions.BottomRow - gStatementDimensions.TopRow;\r
+\r
+ gST->ConOut->SetAttribute (gST->ConOut, GetPopupColor ());\r
+\r
+ if ((RequestedWidth + 2) > DimensionsWidth) {\r
+ RequestedWidth = DimensionsWidth - 2;\r
+ }\r
+\r
+ //\r
+ // Subtract the PopUp width from total Columns, allow for one space extra on\r
+ // each end plus a border.\r
+ //\r
+ Start = (DimensionsWidth - RequestedWidth - 2) / 2 + gStatementDimensions.LeftColumn + 1;\r
+ End = Start + RequestedWidth + 1;\r
+\r
+ Top = ((DimensionsHeight - NumberOfLines - 2) / 2) + gStatementDimensions.TopRow - 1;\r
+ Bottom = Top + NumberOfLines + 2;\r
+\r
+ Character = BOXDRAW_DOWN_RIGHT;\r
+ PrintCharAt (Start, Top, Character);\r
+ Character = BOXDRAW_HORIZONTAL;\r
+ for (Index = Start; Index + 2 < End; Index++) {\r
+ PrintCharAt ((UINTN)-1, (UINTN)-1, Character);\r
+ }\r
+\r
+ Character = BOXDRAW_DOWN_LEFT;\r
+ PrintCharAt ((UINTN)-1, (UINTN)-1, Character);\r
+ Character = BOXDRAW_VERTICAL;\r
+\r
+ Count = 0;\r
+ for (Index = Top; Index + 2 < Bottom; Index++, Count++) {\r
+ String = VA_ARG (Marker, CHAR16*);\r
+\r
+ //\r
+ // This will clear the background of the line - we never know who might have been\r
+ // here before us. This differs from the next clear in that it used the non-reverse\r
+ // video for normal printing.\r
+ //\r
+ if (GetStringWidth (String) / 2 > 1) {\r
+ ClearLines (Start, End, Index + 1, Index + 1, GetPopupColor ());\r
+ }\r
+\r
+ //\r
+ // Passing in a space results in the assumption that this is where typing will occur\r
+ //\r
+ if (String[0] == L' ') {\r
+ ClearLines (Start + 1, End - 1, Index + 1, Index + 1, GetPopupInverseColor ());\r
+ }\r
+\r
+ //\r
+ // Passing in a NULL results in a blank space\r
+ //\r
+ if (String[0] == CHAR_NULL) {\r
+ ClearLines (Start, End, Index + 1, Index + 1, GetPopupColor ());\r
+ }\r
+\r
+ PrintStringAt (\r
+ ((DimensionsWidth - GetStringWidth (String) / 2) / 2) + gStatementDimensions.LeftColumn + 1,\r
+ Index + 1,\r
+ String\r
+ );\r
+ gST->ConOut->SetAttribute (gST->ConOut, GetPopupColor ());\r
+ PrintCharAt (Start, Index + 1, Character);\r
+ PrintCharAt (End - 1, Index + 1, Character);\r
+ }\r
+\r
+ Character = BOXDRAW_UP_RIGHT;\r
+ PrintCharAt (Start, Bottom - 1, Character);\r
+ Character = BOXDRAW_HORIZONTAL;\r
+ for (Index = Start; Index + 2 < End; Index++) {\r
+ PrintCharAt ((UINTN)-1, (UINTN)-1, Character);\r
+ }\r
+\r
+ Character = BOXDRAW_UP_LEFT;\r
+ PrintCharAt ((UINTN)-1, (UINTN)-1, Character);\r
+}\r
+\r
+/**\r
+ Draw a pop up windows based on the dimension, number of lines and\r
+ strings specified.\r
+\r
+ @param RequestedWidth The width of the pop-up.\r
+ @param NumberOfLines The number of lines.\r
+ @param ... A series of text strings that displayed in the pop-up.\r
+\r
+**/\r
+VOID\r
+EFIAPI\r
+CreateMultiStringPopUp (\r
+ IN UINTN RequestedWidth,\r
+ IN UINTN NumberOfLines,\r
+ ...\r
+ )\r
+{\r
+ VA_LIST Marker;\r
+\r
+ VA_START (Marker, NumberOfLines);\r
+\r
+ CreateSharedPopUp (RequestedWidth, NumberOfLines, Marker);\r
+\r
+ VA_END (Marker);\r
+}\r
+\r
+/**\r
+ Process validate for one question.\r
+\r
+ @param Question The question need to be validate.\r
+\r
+ @retval EFI_SUCCESS Question Option process success.\r
+ @retval EFI_INVALID_PARAMETER Question Option process fail.\r
+\r
+**/\r
+EFI_STATUS \r
+ValidateQuestion (\r
+ IN FORM_DISPLAY_ENGINE_STATEMENT *Question\r
+ )\r
+{\r
+ CHAR16 *ErrorInfo;\r
+ EFI_INPUT_KEY Key;\r
+ EFI_STATUS Status;\r
+ STATEMENT_ERROR_INFO RetInfo;\r
+ UINT32 RetVal;\r
+\r
+ if (Question->ValidateQuestion == NULL) {\r
+ return EFI_SUCCESS;\r
+ }\r
+\r
+ Status = EFI_SUCCESS; \r
+ RetVal = Question->ValidateQuestion(gFormData, Question, &gUserInput->InputValue, &RetInfo);\r
+ \r
+ switch (RetVal) {\r
+ case INCOSISTENT_IF_TRUE:\r
+ //\r
+ // Condition meet, show up error message\r
+ //\r
+ ASSERT (RetInfo.StringId != 0);\r
+ ErrorInfo = GetToken (RetInfo.StringId, gFormData->HiiHandle);\r
+ do {\r
+ CreateDialog (&Key, gEmptyString, ErrorInfo, gPressEnter, gEmptyString, NULL);\r
+ } while (Key.UnicodeChar != CHAR_CARRIAGE_RETURN);\r
+ FreePool (ErrorInfo);\r
+\r
+ Status = EFI_INVALID_PARAMETER;\r
+ break;\r
+\r
+ default:\r
+ break;\r
+ }\r
+\r
+ return Status;\r
+}\r
+\r
+/**\r
+ Display error message for invalid password.\r
+\r
+**/\r
+VOID\r
+PasswordInvalid (\r
+ VOID\r
+ )\r
+{\r
+ EFI_INPUT_KEY Key;\r
+\r
+ //\r
+ // Invalid password, prompt error message\r
+ //\r
+ do {\r
+ CreateDialog (&Key, gEmptyString, gPassowordInvalid, gPressEnter, gEmptyString, NULL);\r
+ } while (Key.UnicodeChar != CHAR_CARRIAGE_RETURN);\r
+}\r
+\r
+/**\r
+ Process password op code.\r
+\r
+ @param MenuOption The menu for current password op code.\r
+\r
+ @retval EFI_SUCCESS Question Option process success.\r
+ @retval Other Question Option process fail.\r
+\r
+**/\r
+EFI_STATUS\r
+PasswordProcess (\r
+ IN UI_MENU_OPTION *MenuOption\r
+ )\r
+{\r
+ CHAR16 *StringPtr;\r
+ CHAR16 *TempString;\r
+ UINTN Maximum;\r
+ EFI_STATUS Status;\r
+ EFI_IFR_PASSWORD *PasswordInfo;\r
+ FORM_DISPLAY_ENGINE_STATEMENT *Question;\r
+ EFI_INPUT_KEY Key;\r
+\r
+ Question = MenuOption->ThisTag;\r
+ PasswordInfo = (EFI_IFR_PASSWORD *) Question->OpCode;\r
+ Maximum = PasswordInfo->MaxSize;\r
+ Status = EFI_SUCCESS;\r
+\r
+ StringPtr = AllocateZeroPool ((Maximum + 1) * sizeof (CHAR16));\r
+ ASSERT (StringPtr);\r
+ \r
+ //\r
+ // Use a NULL password to test whether old password is required\r
+ //\r
+ *StringPtr = 0;\r
+ Status = Question->PasswordCheck (gFormData, Question, StringPtr);\r
+ if (Status == EFI_NOT_AVAILABLE_YET || Status == EFI_UNSUPPORTED) {\r
+ //\r
+ // Password can't be set now. \r
+ //\r
+ FreePool (StringPtr);\r
+ return EFI_SUCCESS;\r
+ }\r
+\r
+ if (EFI_ERROR (Status)) {\r
+ //\r
+ // Old password exist, ask user for the old password\r
+ //\r
+ Status = ReadString (MenuOption, gPromptForPassword, StringPtr);\r
+ if (EFI_ERROR (Status)) {\r
+ FreePool (StringPtr);\r
+ return Status;\r
+ }\r
+\r
+ //\r
+ // Check user input old password\r
+ //\r
+ Status = Question->PasswordCheck (gFormData, Question, StringPtr);\r
+ if (EFI_ERROR (Status)) {\r
+ if (Status == EFI_NOT_READY) {\r
+ //\r
+ // Typed in old password incorrect\r
+ //\r
+ PasswordInvalid ();\r
+ } else {\r
+ Status = EFI_SUCCESS;\r
+ }\r
+\r
+ FreePool (StringPtr);\r
+ return Status;\r
+ }\r
+ }\r
+ \r
+ //\r
+ // Ask for new password\r
+ //\r
+ ZeroMem (StringPtr, (Maximum + 1) * sizeof (CHAR16));\r
+ Status = ReadString (MenuOption, gPromptForNewPassword, StringPtr);\r
+ if (EFI_ERROR (Status)) {\r
+ //\r
+ // Reset state machine for password\r
+ //\r
+ Question->PasswordCheck (gFormData, Question, NULL);\r
+ FreePool (StringPtr);\r
+ return Status;\r
+ }\r
+ \r
+ //\r
+ // Confirm new password\r
+ //\r
+ TempString = AllocateZeroPool ((Maximum + 1) * sizeof (CHAR16));\r
+ ASSERT (TempString);\r
+ Status = ReadString (MenuOption, gConfirmPassword, TempString);\r
+ if (EFI_ERROR (Status)) {\r
+ //\r
+ // Reset state machine for password\r
+ //\r
+ Question->PasswordCheck (gFormData, Question, NULL);\r
+ FreePool (StringPtr);\r
+ FreePool (TempString);\r
+ return Status;\r
+ }\r
+ \r
+ //\r
+ // Compare two typed-in new passwords\r
+ //\r
+ if (StrCmp (StringPtr, TempString) == 0) { \r
+ gUserInput->InputValue.Buffer = AllocateCopyPool (Question->CurrentValue.BufferLen, StringPtr);\r
+ gUserInput->InputValue.BufferLen = Question->CurrentValue.BufferLen;\r
+ gUserInput->InputValue.Type = Question->CurrentValue.Type;\r
+ gUserInput->InputValue.Value.string = HiiSetString(gFormData->HiiHandle, gUserInput->InputValue.Value.string, StringPtr, NULL);\r
+ FreePool (StringPtr); \r
+\r
+ Status = ValidateQuestion (Question);\r
+\r
+ if (EFI_ERROR (Status)) {\r
+ //\r
+ // Reset state machine for password\r
+ //\r
+ Question->PasswordCheck (gFormData, Question, NULL);\r
+ }\r
+\r
+ return Status;\r
+ } else {\r
+ //\r
+ // Reset state machine for password\r
+ //\r
+ Question->PasswordCheck (gFormData, Question, NULL);\r
+ \r
+ //\r
+ // Two password mismatch, prompt error message\r
+ //\r
+ do {\r
+ CreateDialog (&Key, gEmptyString, gConfirmError, gPressEnter, gEmptyString, NULL);\r
+ } while (Key.UnicodeChar != CHAR_CARRIAGE_RETURN);\r
+\r
+ Status = EFI_INVALID_PARAMETER;\r
+ }\r
+ \r
+ FreePool (TempString);\r
+ FreePool (StringPtr);\r
+\r
+ return Status;\r
+}\r
+\r
+/**\r
+ Process a Question's Option (whether selected or un-selected).\r
+\r
+ @param MenuOption The MenuOption for this Question.\r
+ @param Selected TRUE: if Question is selected.\r
+ @param OptionString Pointer of the Option String to be displayed.\r
+ @param SkipErrorValue Whether need to return when value without option for it.\r
+\r
+ @retval EFI_SUCCESS Question Option process success.\r
+ @retval Other Question Option process fail.\r
+\r
+**/\r
+EFI_STATUS\r
+ProcessOptions (\r
+ IN UI_MENU_OPTION *MenuOption,\r
+ IN BOOLEAN Selected,\r
+ OUT CHAR16 **OptionString,\r
+ IN BOOLEAN SkipErrorValue\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ CHAR16 *StringPtr;\r
+ UINTN Index;\r
+ FORM_DISPLAY_ENGINE_STATEMENT *Question;\r
+ CHAR16 FormattedNumber[21];\r
+ UINT16 Number;\r
+ CHAR16 Character[2];\r
+ EFI_INPUT_KEY Key;\r
+ UINTN BufferSize;\r
+ DISPLAY_QUESTION_OPTION *OneOfOption;\r
+ LIST_ENTRY *Link;\r
+ EFI_HII_VALUE HiiValue;\r
+ EFI_HII_VALUE *QuestionValue;\r
+ DISPLAY_QUESTION_OPTION *Option;\r
+ UINTN Index2;\r
+ UINT8 *ValueArray;\r
+ UINT8 ValueType;\r
+ EFI_STRING_ID StringId;\r
+ EFI_IFR_ORDERED_LIST *OrderList;\r
+ BOOLEAN ValueInvalid;\r
+\r
+ Status = EFI_SUCCESS;\r
+\r
+ StringPtr = NULL;\r
+ Character[1] = L'\0';\r
+ *OptionString = NULL;\r
+ StringId = 0;\r
+ ValueInvalid = FALSE;\r
+\r
+ ZeroMem (FormattedNumber, 21 * sizeof (CHAR16));\r
+ BufferSize = (gOptionBlockWidth + 1) * 2 * gStatementDimensions.BottomRow;\r
+\r
+ Question = MenuOption->ThisTag;\r
+ QuestionValue = &Question->CurrentValue;\r
+\r
+ switch (Question->OpCode->OpCode) {\r
+ case EFI_IFR_ORDERED_LIST_OP:\r
+\r
+ //\r
+ // Check whether there are Options of this OrderedList\r
+ //\r
+ if (IsListEmpty (&Question->OptionListHead)) {\r
+ break;\r
+ }\r
+\r
+ OrderList = (EFI_IFR_ORDERED_LIST *) Question->OpCode;\r
+\r
+ Link = GetFirstNode (&Question->OptionListHead);\r
+ OneOfOption = DISPLAY_QUESTION_OPTION_FROM_LINK (Link);\r
+\r
+ ValueType = OneOfOption->OptionOpCode->Type;\r
+ ValueArray = Question->CurrentValue.Buffer;\r
+\r
+ if (Selected) {\r
+ //\r
+ // Go ask for input\r
+ //\r
+ Status = GetSelectionInputPopUp (MenuOption);\r
+ } else {\r
+ //\r
+ // We now know how many strings we will have, so we can allocate the\r
+ // space required for the array or strings.\r
+ //\r
+ *OptionString = AllocateZeroPool (OrderList->MaxContainers * BufferSize);\r
+ ASSERT (*OptionString);\r
+\r
+ HiiValue.Type = ValueType;\r
+ HiiValue.Value.u64 = 0;\r
+ for (Index = 0; Index < OrderList->MaxContainers; Index++) {\r
+ HiiValue.Value.u64 = GetArrayData (ValueArray, ValueType, Index);\r
+ if (HiiValue.Value.u64 == 0) {\r
+ //\r
+ // Values for the options in ordered lists should never be a 0\r
+ //\r
+ break;\r
+ }\r
+\r
+ OneOfOption = ValueToOption (Question, &HiiValue);\r
+ if (OneOfOption == NULL) {\r
+ if (SkipErrorValue) {\r
+ //\r
+ // Just try to get the option string, skip the value which not has option.\r
+ //\r
+ continue;\r
+ }\r
+\r
+ //\r
+ // Show error message\r
+ //\r
+ do {\r
+ CreateDialog (&Key, gEmptyString, gOptionMismatch, gPressEnter, gEmptyString, NULL);\r
+ } while (Key.UnicodeChar != CHAR_CARRIAGE_RETURN);\r
+\r
+ //\r
+ // The initial value of the orderedlist is invalid, force to be valid value\r
+ // Exit current DisplayForm with new value.\r
+ //\r
+ gUserInput->SelectedStatement = Question;\r
+ \r
+ ValueArray = AllocateZeroPool (Question->CurrentValue.BufferLen);\r
+ ASSERT (ValueArray != NULL);\r
+ gUserInput->InputValue.Buffer = ValueArray;\r
+ gUserInput->InputValue.BufferLen = Question->CurrentValue.BufferLen;\r
+ gUserInput->InputValue.Type = Question->CurrentValue.Type;\r
+ \r
+ Link = GetFirstNode (&Question->OptionListHead);\r
+ Index2 = 0;\r
+ while (!IsNull (&Question->OptionListHead, Link) && Index2 < OrderList->MaxContainers) {\r
+ Option = DISPLAY_QUESTION_OPTION_FROM_LINK (Link);\r
+ Link = GetNextNode (&Question->OptionListHead, Link);\r
+ SetArrayData (ValueArray, ValueType, Index2, Option->OptionOpCode->Value.u64);\r
+ Index2++;\r
+ }\r
+ SetArrayData (ValueArray, ValueType, Index2, 0);\r
+\r
+ FreePool (*OptionString);\r
+ *OptionString = NULL;\r
+ return EFI_NOT_FOUND;\r
+ }\r
+\r
+ Character[0] = LEFT_ONEOF_DELIMITER;\r
+ NewStrCat (OptionString[0], Character);\r
+ StringPtr = GetToken (OneOfOption->OptionOpCode->Option, gFormData->HiiHandle);\r
+ ASSERT (StringPtr != NULL);\r
+ NewStrCat (OptionString[0], StringPtr);\r
+ Character[0] = RIGHT_ONEOF_DELIMITER;\r
+ NewStrCat (OptionString[0], Character);\r
+ Character[0] = CHAR_CARRIAGE_RETURN;\r
+ NewStrCat (OptionString[0], Character);\r
+ FreePool (StringPtr);\r
+ }\r
+\r
+ //\r
+ // If valid option more than the max container, skip these options.\r
+ //\r
+ if (Index >= OrderList->MaxContainers) {\r
+ break;\r
+ }\r
+\r
+ //\r
+ // Search the other options, try to find the one not in the container.\r
+ //\r
+ Link = GetFirstNode (&Question->OptionListHead);\r
+ while (!IsNull (&Question->OptionListHead, Link)) {\r
+ OneOfOption = DISPLAY_QUESTION_OPTION_FROM_LINK (Link);\r
+ Link = GetNextNode (&Question->OptionListHead, Link);\r
+\r
+ if (FindArrayData (ValueArray, ValueType, OneOfOption->OptionOpCode->Value.u64, NULL)) {\r
+ continue;\r
+ }\r
+\r
+ if (SkipErrorValue) {\r
+ //\r
+ // Not report error, just get the correct option string info.\r
+ //\r
+ Character[0] = LEFT_ONEOF_DELIMITER;\r
+ NewStrCat (OptionString[0], Character);\r
+ StringPtr = GetToken (OneOfOption->OptionOpCode->Option, gFormData->HiiHandle);\r
+ ASSERT (StringPtr != NULL);\r
+ NewStrCat (OptionString[0], StringPtr);\r
+ Character[0] = RIGHT_ONEOF_DELIMITER;\r
+ NewStrCat (OptionString[0], Character);\r
+ Character[0] = CHAR_CARRIAGE_RETURN;\r
+ NewStrCat (OptionString[0], Character);\r
+ FreePool (StringPtr);\r
+\r
+ continue;\r
+ }\r
+\r
+ if (!ValueInvalid) {\r
+ ValueInvalid = TRUE;\r
+ //\r
+ // Show error message\r
+ //\r
+ do {\r
+ CreateDialog (&Key, gEmptyString, gOptionMismatch, gPressEnter, gEmptyString, NULL);\r
+ } while (Key.UnicodeChar != CHAR_CARRIAGE_RETURN);\r
+\r
+ //\r
+ // The initial value of the orderedlist is invalid, force to be valid value\r
+ // Exit current DisplayForm with new value.\r
+ //\r
+ gUserInput->SelectedStatement = Question;\r
+ \r
+ ValueArray = AllocateCopyPool (Question->CurrentValue.BufferLen, Question->CurrentValue.Buffer);\r
+ ASSERT (ValueArray != NULL);\r
+ gUserInput->InputValue.Buffer = ValueArray;\r
+ gUserInput->InputValue.BufferLen = Question->CurrentValue.BufferLen;\r
+ gUserInput->InputValue.Type = Question->CurrentValue.Type;\r
+ }\r
+ \r
+ SetArrayData (ValueArray, ValueType, Index++, OneOfOption->OptionOpCode->Value.u64);\r
+ }\r
+\r
+ if (ValueInvalid) {\r
+ FreePool (*OptionString);\r
+ *OptionString = NULL;\r
+ return EFI_NOT_FOUND;\r
+ }\r
+ }\r
+ break;\r
+\r
+ case EFI_IFR_ONE_OF_OP:\r
+ //\r
+ // Check whether there are Options of this OneOf\r
+ //\r
+ if (IsListEmpty (&Question->OptionListHead)) {\r
+ break;\r
+ }\r
+ if (Selected) {\r
+ //\r
+ // Go ask for input\r
+ //\r
+ Status = GetSelectionInputPopUp (MenuOption);\r
+ } else {\r
+ *OptionString = AllocateZeroPool (BufferSize);\r
+ ASSERT (*OptionString);\r
+\r
+ OneOfOption = ValueToOption (Question, QuestionValue);\r
+ if (OneOfOption == NULL) {\r
+ if (SkipErrorValue) {\r
+ //\r
+ // Not report error, just get the correct option string info.\r
+ // \r
+ Link = GetFirstNode (&Question->OptionListHead);\r
+ OneOfOption = DISPLAY_QUESTION_OPTION_FROM_LINK (Link);\r
+ } else {\r
+ //\r
+ // Show error message\r
+ //\r
+ do {\r
+ CreateDialog (&Key, gEmptyString, gOptionMismatch, gPressEnter, gEmptyString, NULL);\r
+ } while (Key.UnicodeChar != CHAR_CARRIAGE_RETURN);\r
+\r
+ //\r
+ // Force the Question value to be valid\r
+ // Exit current DisplayForm with new value.\r
+ //\r
+ Link = GetFirstNode (&Question->OptionListHead);\r
+ Option = DISPLAY_QUESTION_OPTION_FROM_LINK (Link);\r
+\r
+ CopyMem (&gUserInput->InputValue.Value, &Option->OptionOpCode->Value, sizeof (EFI_IFR_TYPE_VALUE));\r
+ gUserInput->InputValue.Type = Option->OptionOpCode->Type;\r
+ gUserInput->SelectedStatement = Question;\r
+\r
+ FreePool (*OptionString);\r
+ *OptionString = NULL;\r
+ return EFI_NOT_FOUND;\r
+ }\r
+ }\r
+\r
+ Character[0] = LEFT_ONEOF_DELIMITER;\r
+ NewStrCat (OptionString[0], Character);\r
+ StringPtr = GetToken (OneOfOption->OptionOpCode->Option, gFormData->HiiHandle);\r
+ ASSERT (StringPtr != NULL);\r
+ NewStrCat (OptionString[0], StringPtr);\r
+ Character[0] = RIGHT_ONEOF_DELIMITER;\r
+ NewStrCat (OptionString[0], Character);\r
+\r
+ FreePool (StringPtr);\r
+ }\r
+ break;\r
+\r
+ case EFI_IFR_CHECKBOX_OP:\r
+ if (Selected) {\r
+ //\r
+ // Since this is a BOOLEAN operation, flip it upon selection\r
+ //\r
+ gUserInput->InputValue.Type = QuestionValue->Type;\r
+ gUserInput->InputValue.Value.b = (BOOLEAN) (QuestionValue->Value.b ? FALSE : TRUE);\r
+\r
+ //\r
+ // Perform inconsistent check\r
+ //\r
+ return ValidateQuestion (Question);\r
+ } else { \r
+ *OptionString = AllocateZeroPool (BufferSize);\r
+ ASSERT (*OptionString);\r
+\r
+ *OptionString[0] = LEFT_CHECKBOX_DELIMITER;\r
+\r
+ if (QuestionValue->Value.b) {\r
+ *(OptionString[0] + 1) = CHECK_ON;\r
+ } else {\r
+ *(OptionString[0] + 1) = CHECK_OFF;\r
+ }\r
+ *(OptionString[0] + 2) = RIGHT_CHECKBOX_DELIMITER;\r
+ }\r
+ break;\r
+\r
+ case EFI_IFR_NUMERIC_OP:\r
+ if (Selected) {\r
+ //\r
+ // Go ask for input\r
+ //\r
+ Status = GetNumericInput (MenuOption);\r
+ } else {\r
+ *OptionString = AllocateZeroPool (BufferSize);\r
+ ASSERT (*OptionString);\r
+\r
+ *OptionString[0] = LEFT_NUMERIC_DELIMITER;\r
+\r
+ //\r
+ // Formatted print\r
+ //\r
+ PrintFormattedNumber (Question, FormattedNumber, 21 * sizeof (CHAR16));\r
+ Number = (UINT16) GetStringWidth (FormattedNumber);\r
+ CopyMem (OptionString[0] + 1, FormattedNumber, Number);\r
+\r
+ *(OptionString[0] + Number / 2) = RIGHT_NUMERIC_DELIMITER;\r
+ }\r
+ break;\r
+\r
+ case EFI_IFR_DATE_OP:\r
+ if (Selected) {\r
+ //\r
+ // This is similar to numerics\r
+ //\r
+ Status = GetNumericInput (MenuOption);\r
+ } else {\r
+ *OptionString = AllocateZeroPool (BufferSize);\r
+ ASSERT (*OptionString);\r
+\r
+ switch (MenuOption->Sequence) {\r
+ case 0:\r
+ *OptionString[0] = LEFT_NUMERIC_DELIMITER;\r
+ UnicodeSPrint (OptionString[0] + 1, 21 * sizeof (CHAR16), L"%02d", QuestionValue->Value.date.Month);\r
+ *(OptionString[0] + 3) = DATE_SEPARATOR;\r
+ break;\r
+\r
+ case 1:\r
+ SetUnicodeMem (OptionString[0], 4, L' ');\r
+ UnicodeSPrint (OptionString[0] + 4, 21 * sizeof (CHAR16), L"%02d", QuestionValue->Value.date.Day);\r
+ *(OptionString[0] + 6) = DATE_SEPARATOR;\r
+ break;\r
+\r
+ case 2:\r
+ SetUnicodeMem (OptionString[0], 7, L' ');\r
+ UnicodeSPrint (OptionString[0] + 7, 21 * sizeof (CHAR16), L"%04d", QuestionValue->Value.date.Year);\r
+ *(OptionString[0] + 11) = RIGHT_NUMERIC_DELIMITER;\r
+ break;\r
+ }\r
+ }\r
+ break;\r
+\r
+ case EFI_IFR_TIME_OP:\r
+ if (Selected) {\r
+ //\r
+ // This is similar to numerics\r
+ //\r
+ Status = GetNumericInput (MenuOption);\r
+ } else {\r
+ *OptionString = AllocateZeroPool (BufferSize);\r
+ ASSERT (*OptionString);\r
+\r
+ switch (MenuOption->Sequence) {\r
+ case 0:\r
+ *OptionString[0] = LEFT_NUMERIC_DELIMITER;\r
+ UnicodeSPrint (OptionString[0] + 1, 21 * sizeof (CHAR16), L"%02d", QuestionValue->Value.time.Hour);\r
+ *(OptionString[0] + 3) = TIME_SEPARATOR;\r
+ break;\r
+\r
+ case 1:\r
+ SetUnicodeMem (OptionString[0], 4, L' ');\r
+ UnicodeSPrint (OptionString[0] + 4, 21 * sizeof (CHAR16), L"%02d", QuestionValue->Value.time.Minute);\r
+ *(OptionString[0] + 6) = TIME_SEPARATOR;\r
+ break;\r
+\r
+ case 2:\r
+ SetUnicodeMem (OptionString[0], 7, L' ');\r
+ UnicodeSPrint (OptionString[0] + 7, 21 * sizeof (CHAR16), L"%02d", QuestionValue->Value.time.Second);\r
+ *(OptionString[0] + 9) = RIGHT_NUMERIC_DELIMITER;\r
+ break;\r
+ }\r
+ }\r
+ break;\r
+\r
+ case EFI_IFR_STRING_OP:\r
+ if (Selected) {\r
+ StringPtr = AllocateZeroPool (Question->CurrentValue.BufferLen + sizeof (CHAR16));\r
+ ASSERT (StringPtr);\r
+ CopyMem(StringPtr, Question->CurrentValue.Buffer, Question->CurrentValue.BufferLen);\r
+\r
+ Status = ReadString (MenuOption, gPromptForData, StringPtr);\r
+ if (EFI_ERROR (Status)) {\r
+ FreePool (StringPtr);\r
+ return Status;\r
+ }\r
+ \r
+ gUserInput->InputValue.Buffer = AllocateCopyPool (Question->CurrentValue.BufferLen, StringPtr);\r
+ gUserInput->InputValue.BufferLen = Question->CurrentValue.BufferLen;\r
+ gUserInput->InputValue.Type = Question->CurrentValue.Type;\r
+ gUserInput->InputValue.Value.string = HiiSetString(gFormData->HiiHandle, gUserInput->InputValue.Value.string, StringPtr, NULL);\r
+ FreePool (StringPtr);\r
+ return ValidateQuestion (Question);\r
+ } else {\r
+ *OptionString = AllocateZeroPool (BufferSize);\r
+ ASSERT (*OptionString);\r
+\r
+ if (((CHAR16 *) Question->CurrentValue.Buffer)[0] == 0x0000) {\r
+ *(OptionString[0]) = '_';\r
+ } else {\r
+ if (Question->CurrentValue.BufferLen < BufferSize) {\r
+ BufferSize = Question->CurrentValue.BufferLen;\r
+ }\r
+ CopyMem (OptionString[0], (CHAR16 *) Question->CurrentValue.Buffer, BufferSize);\r
+ }\r
+ }\r
+ break;\r
+\r
+ case EFI_IFR_PASSWORD_OP:\r
+ if (Selected) {\r
+ Status = PasswordProcess (MenuOption);\r
+ }\r
+ break;\r
+\r
+ default:\r
+ break;\r
+ }\r
+\r
+ return Status;\r
+}\r
+\r
+\r
+/**\r
+ Process the help string: Split StringPtr to several lines of strings stored in\r
+ FormattedString and the glyph width of each line cannot exceed gHelpBlockWidth.\r
+\r
+ @param StringPtr The entire help string.\r
+ @param FormattedString The oupput formatted string.\r
+ @param EachLineWidth The max string length of each line in the formatted string.\r
+ @param RowCount TRUE: if Question is selected.\r
+\r
+**/\r
+UINTN\r
+ProcessHelpString (\r
+ IN CHAR16 *StringPtr,\r
+ OUT CHAR16 **FormattedString,\r
+ OUT UINT16 *EachLineWidth,\r
+ IN UINTN RowCount\r
+ )\r
+{\r
+ UINTN Index;\r
+ CHAR16 *OutputString;\r
+ UINTN TotalRowNum;\r
+ UINTN CheckedNum;\r
+ UINT16 GlyphWidth;\r
+ UINT16 LineWidth;\r
+ UINT16 MaxStringLen;\r
+ UINT16 StringLen;\r
+\r
+ TotalRowNum = 0;\r
+ CheckedNum = 0;\r
+ GlyphWidth = 1;\r
+ Index = 0;\r
+ MaxStringLen = 0;\r
+ StringLen = 0;\r
+\r
+ //\r
+ // Set default help string width.\r
+ //\r
+ LineWidth = (UINT16) (gHelpBlockWidth - 1);\r
+\r
+ //\r
+ // Get row number of the String.\r
+ //\r
+ while ((StringLen = GetLineByWidth (StringPtr, LineWidth, &GlyphWidth, &Index, &OutputString)) != 0) {\r
+ if (StringLen > MaxStringLen) {\r
+ MaxStringLen = StringLen;\r
+ }\r
+\r
+ TotalRowNum ++;\r
+ FreePool (OutputString);\r
+ }\r
+ *EachLineWidth = MaxStringLen;\r
+\r
+ *FormattedString = AllocateZeroPool (TotalRowNum * MaxStringLen * sizeof (CHAR16));\r
+ ASSERT (*FormattedString != NULL);\r
+\r
+ //\r
+ // Generate formatted help string array.\r
+ //\r
+ GlyphWidth = 1;\r
+ Index = 0;\r
+ while((StringLen = GetLineByWidth (StringPtr, LineWidth, &GlyphWidth, &Index, &OutputString)) != 0) {\r
+ CopyMem (*FormattedString + CheckedNum * MaxStringLen, OutputString, StringLen * sizeof (CHAR16));\r
+ CheckedNum ++;\r
+ FreePool (OutputString);\r
+ }\r
+\r
+ return TotalRowNum; \r
+}\r
+++ /dev/null
-/** @file\r
-MACRO definitions for color used in Setup Browser.\r
-\r
-Copyright (c) 2004 - 2011, 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
-THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
-WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
-\r
-**/\r
-//\r
-// Unicode collation protocol in\r
-\r
-#ifndef _COLORS_H_\r
-#define _COLORS_H_\r
-\r
-//\r
-// Screen Color Settings\r
-//\r
-#define PICKLIST_HIGHLIGHT_TEXT EFI_WHITE\r
-#define PICKLIST_HIGHLIGHT_BACKGROUND EFI_BACKGROUND_CYAN\r
-#define TITLE_TEXT EFI_WHITE\r
-#define TITLE_BACKGROUND EFI_BACKGROUND_BLUE\r
-#define KEYHELP_TEXT EFI_LIGHTGRAY\r
-#define KEYHELP_BACKGROUND EFI_BACKGROUND_BLACK\r
-#define SUBTITLE_BACKGROUND EFI_BACKGROUND_LIGHTGRAY\r
-#define BANNER_TEXT EFI_BLUE\r
-#define BANNER_BACKGROUND EFI_BACKGROUND_LIGHTGRAY\r
-#define FIELD_TEXT_GRAYED EFI_DARKGRAY\r
-#define FIELD_BACKGROUND EFI_BACKGROUND_LIGHTGRAY\r
-#define POPUP_TEXT EFI_LIGHTGRAY\r
-#define POPUP_BACKGROUND EFI_BACKGROUND_BLUE\r
-#define POPUP_INVERSE_TEXT EFI_LIGHTGRAY\r
-#define POPUP_INVERSE_BACKGROUND EFI_BACKGROUND_BLACK\r
-#define HELP_TEXT EFI_BLUE\r
-#define ERROR_TEXT EFI_RED | EFI_BRIGHT\r
-#define INFO_TEXT EFI_YELLOW | EFI_BRIGHT\r
-#define ARROW_TEXT EFI_RED | EFI_BRIGHT\r
-#define ARROW_BACKGROUND EFI_BACKGROUND_LIGHTGRAY\r
-\r
-#endif\r
IdToForm (\r
IN FORM_BROWSER_FORMSET *FormSet,\r
IN UINT16 FormId\r
-)\r
+ )\r
{\r
LIST_ENTRY *Link;\r
FORM_BROWSER_FORM *Form;\r
//\r
FormSet = AllocateZeroPool (sizeof (FORM_BROWSER_FORMSET));\r
ASSERT (FormSet != NULL);\r
- Status = InitializeFormSet(HiiHandle, FormSetGuid, FormSet, FALSE);\r
+ Status = InitializeFormSet(HiiHandle, FormSetGuid, FormSet);\r
if (EFI_ERROR (Status)) {\r
GetTheVal = FALSE;\r
goto Done;\r
for (Index = 0; Index < OpCode->ValueWidth; Index ++, TempBuffer --) {\r
StrPtr += UnicodeValueToString (StrPtr, PREFIX_ZERO | RADIX_HEX, *TempBuffer, 2);\r
}\r
- Status = SetValueByName (OpCode->VarStorage, OpCode->ValueName, NameValue, GetSetValueWithEditBuffer);\r
+ Status = SetValueByName (OpCode->VarStorage, OpCode->ValueName, NameValue, GetSetValueWithEditBuffer, NULL);\r
FreePool (NameValue);\r
if (!EFI_ERROR (Status)) {\r
Data1.Value.b = TRUE;\r
--- /dev/null
+/** @file\r
+Private structure, MACRO and function definitions for User Interface related functionalities.\r
+\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
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#ifndef _EXPRESSION_H_\r
+#define _EXPRESSION_H_\r
+\r
+/**\r
+ Get the expression list count.\r
+ \r
+ @param Level Which type this expression belong to. Form, \r
+ statement or option?\r
+\r
+ @retval >=0 The expression count\r
+ @retval -1 Input parameter error.\r
+\r
+**/\r
+INTN \r
+GetConditionalExpressionCount (\r
+ IN EXPRESS_LEVEL Level\r
+ );\r
+\r
+/**\r
+ Reset stack pointer to begin of the stack.\r
+\r
+**/\r
+VOID\r
+ResetCurrentExpressionStack (\r
+ VOID\r
+ );\r
+\r
+/**\r
+ Reset stack pointer to begin of the stack.\r
+\r
+**/\r
+VOID\r
+ResetMapExpressionListStack (\r
+ VOID\r
+ );\r
+\r
+/**\r
+ Reset stack pointer to begin of the stack.\r
+\r
+**/\r
+VOID\r
+ResetScopeStack (\r
+ VOID\r
+ );\r
+\r
+/**\r
+ Push an Operand onto the Stack\r
+\r
+ @param Operand Operand to push.\r
+\r
+ @retval EFI_SUCCESS The value was pushed onto the stack.\r
+ @retval EFI_OUT_OF_RESOURCES There is not enough system memory to grow the\r
+ stack.\r
+\r
+**/\r
+EFI_STATUS\r
+PushScope (\r
+ IN UINT8 Operand\r
+ );\r
+\r
+/**\r
+ Get the expression Buffer pointer.\r
+ \r
+ @param Level Which type this expression belong to. Form, \r
+ statement or option?\r
+\r
+ @retval The start pointer of the expression buffer or NULL.\r
+\r
+**/\r
+FORM_EXPRESSION **\r
+GetConditionalExpressionList (\r
+ IN EXPRESS_LEVEL Level\r
+ );\r
+\r
+/**\r
+ Pop an Operand from the Stack\r
+\r
+ @param Operand Operand to pop.\r
+\r
+ @retval EFI_SUCCESS The value was pushed onto the stack.\r
+ @retval EFI_OUT_OF_RESOURCES There is not enough system memory to grow the\r
+ stack.\r
+\r
+**/\r
+EFI_STATUS\r
+PopScope (\r
+ OUT UINT8 *Operand\r
+ );\r
+\r
+/**\r
+ Push the list of map expression onto the Stack\r
+\r
+ @param Pointer Pointer to the list of map expression to be pushed.\r
+\r
+ @retval EFI_SUCCESS The value was pushed onto the stack.\r
+ @retval EFI_OUT_OF_RESOURCES There is not enough system memory to grow the stack.\r
+\r
+**/\r
+EFI_STATUS\r
+PushMapExpressionList (\r
+ IN VOID *Pointer\r
+ );\r
+\r
+/**\r
+ Push current expression onto the Stack\r
+\r
+ @param Pointer Pointer to current expression.\r
+\r
+ @retval EFI_SUCCESS The value was pushed onto the stack.\r
+ @retval EFI_OUT_OF_RESOURCES There is not enough system memory to grow the stack.\r
+\r
+**/\r
+EFI_STATUS\r
+PushCurrentExpression (\r
+ IN VOID *Pointer\r
+ );\r
+\r
+/**\r
+ Zero extend integer/boolean/date/time to UINT64 for comparing.\r
+\r
+ @param Value HII Value to be converted.\r
+\r
+**/\r
+VOID\r
+ExtendValueToU64 (\r
+ IN EFI_HII_VALUE *Value\r
+ );\r
+\r
+/**\r
+ Push the expression options onto the Stack.\r
+\r
+ @param Pointer Pointer to the current expression.\r
+ @param Level Which type this expression belong to. Form, \r
+ statement or option?\r
+\r
+ @retval EFI_SUCCESS The value was pushed onto the stack.\r
+ @retval EFI_OUT_OF_RESOURCES There is not enough system memory to grow the stack.\r
+\r
+**/\r
+EFI_STATUS\r
+PushConditionalExpression (\r
+ IN FORM_EXPRESSION *Pointer,\r
+ IN EXPRESS_LEVEL Level\r
+ );\r
+\r
+/**\r
+ Pop the expression options from the Stack\r
+\r
+ @param Level Which type this expression belong to. Form, \r
+ statement or option?\r
+\r
+ @retval EFI_SUCCESS The value was pushed onto the stack.\r
+ @retval EFI_OUT_OF_RESOURCES There is not enough system memory to grow the stack.\r
+\r
+**/\r
+EFI_STATUS\r
+PopConditionalExpression (\r
+ IN EXPRESS_LEVEL Level\r
+ );\r
+\r
+/**\r
+ Pop the list of map expression from the Stack\r
+\r
+ @param Pointer Pointer to the list of map expression to be pop.\r
+\r
+ @retval EFI_SUCCESS The value was pushed onto the stack.\r
+ @retval EFI_OUT_OF_RESOURCES There is not enough system memory to grow the stack.\r
+\r
+**/\r
+EFI_STATUS\r
+PopMapExpressionList (\r
+ OUT VOID **Pointer\r
+ );\r
+\r
+/**\r
+ Pop current expression from the Stack\r
+\r
+ @param Pointer Pointer to current expression to be pop.\r
+\r
+ @retval EFI_SUCCESS The value was pushed onto the stack.\r
+ @retval EFI_OUT_OF_RESOURCES There is not enough system memory to grow the stack.\r
+\r
+**/\r
+EFI_STATUS\r
+PopCurrentExpression (\r
+ OUT VOID **Pointer\r
+ );\r
+\r
+/**\r
+ Evaluate the result of a HII expression.\r
+\r
+ If Expression is NULL, then ASSERT.\r
+\r
+ @param FormSet FormSet associated with this expression.\r
+ @param Form Form associated with this expression.\r
+ @param Expression Expression to be evaluated.\r
+\r
+ @retval EFI_SUCCESS The expression evaluated successfuly\r
+ @retval EFI_NOT_FOUND The Question which referenced by a QuestionId\r
+ could not be found.\r
+ @retval EFI_OUT_OF_RESOURCES There is not enough system memory to grow the\r
+ stack.\r
+ @retval EFI_ACCESS_DENIED The pop operation underflowed the stack\r
+ @retval EFI_INVALID_PARAMETER Syntax error with the Expression\r
+\r
+**/\r
+EFI_STATUS\r
+EvaluateExpression (\r
+ IN FORM_BROWSER_FORMSET *FormSet,\r
+ IN FORM_BROWSER_FORM *Form,\r
+ IN OUT FORM_EXPRESSION *Expression\r
+ );\r
+/**\r
+ Return the result of the expression list. Check the expression list and \r
+ return the highest priority express result. \r
+ Priority: DisableIf > SuppressIf > GrayOutIf > FALSE\r
+\r
+ @param ExpList The input expression list.\r
+ @param Evaluate Whether need to evaluate the expression first.\r
+ @param FormSet FormSet associated with this expression.\r
+ @param Form Form associated with this expression. \r
+\r
+ @retval EXPRESS_RESULT Return the higher priority express result. \r
+ DisableIf > SuppressIf > GrayOutIf > FALSE\r
+\r
+**/\r
+EXPRESS_RESULT \r
+EvaluateExpressionList (\r
+ IN FORM_EXPRESSION_LIST *ExpList,\r
+ IN BOOLEAN Evaluate,\r
+ IN FORM_BROWSER_FORMSET *FormSet, OPTIONAL\r
+ IN FORM_BROWSER_FORM *Form OPTIONAL\r
+ );\r
+\r
+/**\r
+ Get Form given its FormId.\r
+\r
+ @param FormSet The formset which contains this form.\r
+ @param FormId Id of this form.\r
+\r
+ @retval Pointer The form.\r
+ @retval NULL Specified Form is not found in the formset.\r
+\r
+**/\r
+FORM_BROWSER_FORM *\r
+IdToForm (\r
+ IN FORM_BROWSER_FORMSET *FormSet,\r
+ IN UINT16 FormId\r
+ );\r
+\r
+#endif // _EXPRESSION_H\r
\r
UINT16 mStatementIndex;\r
UINT16 mExpressionOpCodeIndex;\r
-\r
+EFI_QUESTION_ID mUsedQuestionId;\r
BOOLEAN mInScopeSubtitle;\r
extern LIST_ENTRY gBrowserStorageList;\r
/**\r
\r
if (Form == NULL) {\r
//\r
- // We are currently not in a Form Scope, so just skip this Statement\r
+ // Only guid op may out side the form level.\r
//\r
- return NULL;\r
+ ASSERT (((EFI_IFR_OP_HEADER *) OpCodeData)->OpCode == EFI_IFR_GUID_OP);\r
}\r
\r
Statement = &FormSet->StatementBuffer[mStatementIndex];\r
Statement->Signature = FORM_BROWSER_STATEMENT_SIGNATURE;\r
\r
Statement->Operand = ((EFI_IFR_OP_HEADER *) OpCodeData)->OpCode;\r
+ Statement->OpCode = (EFI_IFR_OP_HEADER *) OpCodeData;\r
\r
StatementHdr = (EFI_IFR_STATEMENT_HEADER *) (OpCodeData + sizeof (EFI_IFR_OP_HEADER));\r
CopyMem (&Statement->Prompt, &StatementHdr->Prompt, sizeof (EFI_STRING_ID));\r
//\r
// Insert this Statement into current Form\r
//\r
- InsertTailList (&Form->StatementListHead, &Statement->Link);\r
-\r
+ if (Form == NULL) {\r
+ InsertTailList (&FormSet->StatementListOSF, &Statement->Link);\r
+ } else {\r
+ InsertTailList (&Form->StatementListHead, &Statement->Link);\r
+ }\r
return Statement;\r
}\r
\r
CountOpCodes (FormSet, &NumberOfStatement, &NumberOfExpression);\r
\r
mStatementIndex = 0;\r
+ mUsedQuestionId = 1;\r
FormSet->StatementBuffer = AllocateZeroPool (NumberOfStatement * sizeof (FORM_BROWSER_STATEMENT));\r
if (FormSet->StatementBuffer == NULL) {\r
return EFI_OUT_OF_RESOURCES;\r
return EFI_OUT_OF_RESOURCES;\r
}\r
\r
+ InitializeListHead (&FormSet->StatementListOSF);\r
InitializeListHead (&FormSet->StorageListHead);\r
InitializeListHead (&FormSet->DefaultStoreListHead);\r
InitializeListHead (&FormSet->FormListHead);\r
InitializeListHead (&CurrentForm->ConfigRequestHead);\r
\r
CurrentForm->FormType = STANDARD_MAP_FORM_TYPE;\r
- CurrentForm->NvUpdateRequired = FALSE;\r
CopyMem (&CurrentForm->FormId, &((EFI_IFR_FORM *) OpCodeData)->FormId, sizeof (UINT16));\r
CopyMem (&CurrentForm->FormTitle, &((EFI_IFR_FORM *) OpCodeData)->FormTitle, sizeof (EFI_STRING_ID));\r
\r
CurrentForm = AllocateZeroPool (sizeof (FORM_BROWSER_FORM));\r
ASSERT (CurrentForm != NULL);\r
CurrentForm->Signature = FORM_BROWSER_FORM_SIGNATURE;\r
- CurrentForm->NvUpdateRequired = FALSE;\r
InitializeListHead (&CurrentForm->ExpressionListHead);\r
InitializeListHead (&CurrentForm->StatementListHead);\r
InitializeListHead (&CurrentForm->ConfigRequestHead);\r
ASSERT (CurrentStatement != NULL);\r
\r
CurrentStatement->Flags = ((EFI_IFR_SUBTITLE *) OpCodeData)->Flags;\r
-\r
+ CurrentStatement->FakeQuestionId = mUsedQuestionId++;\r
if (Scope != 0) {\r
mInScopeSubtitle = TRUE;\r
}\r
case EFI_IFR_TEXT_OP:\r
CurrentStatement = CreateStatement (OpCodeData, FormSet, CurrentForm);\r
ASSERT (CurrentStatement != NULL);\r
-\r
+ CurrentStatement->FakeQuestionId = mUsedQuestionId++;\r
CopyMem (&CurrentStatement->TextTwo, &((EFI_IFR_TEXT *) OpCodeData)->TextTwo, sizeof (EFI_STRING_ID));\r
break;\r
\r
case EFI_IFR_RESET_BUTTON_OP:\r
CurrentStatement = CreateStatement (OpCodeData, FormSet, CurrentForm);\r
ASSERT (CurrentStatement != NULL);\r
+ CurrentStatement->FakeQuestionId = mUsedQuestionId++;\r
CopyMem (&CurrentStatement->DefaultId, &((EFI_IFR_RESET_BUTTON *) OpCodeData)->DefaultId, sizeof (EFI_DEFAULT_ID));\r
break;\r
\r
CurrentOption = AllocateZeroPool (sizeof (QUESTION_OPTION));\r
ASSERT (CurrentOption != NULL);\r
CurrentOption->Signature = QUESTION_OPTION_SIGNATURE;\r
+ CurrentOption->OpCode = (EFI_IFR_ONE_OF_OPTION *) OpCodeData;\r
\r
CurrentOption->Flags = ((EFI_IFR_ONE_OF_OPTION *) OpCodeData)->Flags;\r
CurrentOption->Value.Type = ((EFI_IFR_ONE_OF_OPTION *) OpCodeData)->Type;\r
//\r
// Vendor specific\r
//\r
- case EFI_IFR_GUID_OP:\r
- if (CompareGuid (&gEfiIfrTianoGuid, (EFI_GUID *)(OpCodeData + sizeof (EFI_IFR_OP_HEADER)))) {\r
- //\r
- // Tiano specific GUIDed opcodes\r
- //\r
- switch (((EFI_IFR_GUID_LABEL *) OpCodeData)->ExtendOpCode) {\r
- case EFI_IFR_EXTEND_OP_LABEL:\r
- //\r
- // just ignore label\r
- //\r
- break;\r
-\r
- case EFI_IFR_EXTEND_OP_BANNER:\r
- //\r
- // By SubClass to get Banner Data from Front Page\r
- //\r
- if (FormSet->SubClass == EFI_FRONT_PAGE_SUBCLASS) {\r
- CopyMem (\r
- &gBannerData->Banner[((EFI_IFR_GUID_BANNER *) OpCodeData)->LineNumber][\r
- ((EFI_IFR_GUID_BANNER *) OpCodeData)->Alignment],\r
- &((EFI_IFR_GUID_BANNER *) OpCodeData)->Title,\r
- sizeof (EFI_STRING_ID)\r
- );\r
- }\r
- break;\r
-\r
- case EFI_IFR_EXTEND_OP_CLASS:\r
- CopyMem (&FormSet->Class, &((EFI_IFR_GUID_CLASS *) OpCodeData)->Class, sizeof (UINT16));\r
- break;\r
-\r
- case EFI_IFR_EXTEND_OP_SUBCLASS:\r
- CopyMem (&FormSet->SubClass, &((EFI_IFR_GUID_SUBCLASS *) OpCodeData)->SubClass, sizeof (UINT16));\r
- break;\r
-\r
- default:\r
- break;\r
- }\r
- }\r
-\r
+ case EFI_IFR_GUID_OP: \r
+ CurrentStatement = CreateStatement (OpCodeData, FormSet, CurrentForm);\r
break;\r
\r
//\r
+++ /dev/null
-/** @file\r
-Implementation for handling user input from the User Interfaces.\r
-\r
-Copyright (c) 2004 - 2012, 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
-THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
-WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
-\r
-**/\r
-\r
-#include "Setup.h"\r
-\r
-\r
-/**\r
- Get string or password input from user.\r
-\r
- @param MenuOption Pointer to the current input menu.\r
- @param Prompt The prompt string shown on popup window.\r
- @param StringPtr Old user input and destination for use input string.\r
-\r
- @retval EFI_SUCCESS If string input is read successfully\r
- @retval EFI_DEVICE_ERROR If operation fails\r
-\r
-**/\r
-EFI_STATUS\r
-ReadString (\r
- IN UI_MENU_OPTION *MenuOption,\r
- IN CHAR16 *Prompt,\r
- IN OUT CHAR16 *StringPtr\r
- )\r
-{\r
- EFI_STATUS Status;\r
- EFI_INPUT_KEY Key;\r
- CHAR16 NullCharacter;\r
- UINTN ScreenSize;\r
- CHAR16 Space[2];\r
- CHAR16 KeyPad[2];\r
- CHAR16 *TempString;\r
- CHAR16 *BufferedString;\r
- UINTN Index;\r
- UINTN Index2;\r
- UINTN Count;\r
- UINTN Start;\r
- UINTN Top;\r
- UINTN DimensionsWidth;\r
- UINTN DimensionsHeight;\r
- UINTN CurrentCursor;\r
- BOOLEAN CursorVisible;\r
- UINTN Minimum;\r
- UINTN Maximum;\r
- FORM_BROWSER_STATEMENT *Question;\r
- BOOLEAN IsPassword;\r
-\r
- DimensionsWidth = gScreenDimensions.RightColumn - gScreenDimensions.LeftColumn;\r
- DimensionsHeight = gScreenDimensions.BottomRow - gScreenDimensions.TopRow;\r
-\r
- NullCharacter = CHAR_NULL;\r
- ScreenSize = GetStringWidth (Prompt) / sizeof (CHAR16);\r
- Space[0] = L' ';\r
- Space[1] = CHAR_NULL;\r
-\r
- Question = MenuOption->ThisTag;\r
- Minimum = (UINTN) Question->Minimum;\r
- Maximum = (UINTN) Question->Maximum;\r
-\r
- if (Question->Operand == EFI_IFR_PASSWORD_OP) {\r
- IsPassword = TRUE;\r
- } else {\r
- IsPassword = FALSE;\r
- }\r
-\r
- TempString = AllocateZeroPool ((Maximum + 1)* sizeof (CHAR16));\r
- ASSERT (TempString);\r
-\r
- if (ScreenSize < (Maximum + 1)) {\r
- ScreenSize = Maximum + 1;\r
- }\r
-\r
- if ((ScreenSize + 2) > DimensionsWidth) {\r
- ScreenSize = DimensionsWidth - 2;\r
- }\r
-\r
- BufferedString = AllocateZeroPool (ScreenSize * 2);\r
- ASSERT (BufferedString);\r
-\r
- Start = (DimensionsWidth - ScreenSize - 2) / 2 + gScreenDimensions.LeftColumn + 1;\r
- Top = ((DimensionsHeight - 6) / 2) + gScreenDimensions.TopRow - 1;\r
-\r
- //\r
- // Display prompt for string\r
- //\r
- CreateMultiStringPopUp (ScreenSize, 4, &NullCharacter, Prompt, Space, &NullCharacter);\r
-\r
- gST->ConOut->SetAttribute (gST->ConOut, EFI_TEXT_ATTR (EFI_BLACK, EFI_LIGHTGRAY));\r
-\r
- CursorVisible = gST->ConOut->Mode->CursorVisible;\r
- gST->ConOut->EnableCursor (gST->ConOut, TRUE);\r
-\r
- CurrentCursor = GetStringWidth (StringPtr) / 2 - 1;\r
- if (CurrentCursor != 0) {\r
- //\r
- // Show the string which has beed saved before.\r
- //\r
- SetUnicodeMem (BufferedString, ScreenSize - 1, L' ');\r
- PrintStringAt (Start + 1, Top + 3, BufferedString);\r
-\r
- if ((GetStringWidth (StringPtr) / 2) > (DimensionsWidth - 2)) {\r
- Index = (GetStringWidth (StringPtr) / 2) - DimensionsWidth + 2;\r
- } else {\r
- Index = 0;\r
- }\r
-\r
- if (IsPassword) {\r
- gST->ConOut->SetCursorPosition (gST->ConOut, Start + 1, Top + 3);\r
- }\r
-\r
- for (Count = 0; Index + 1 < GetStringWidth (StringPtr) / 2; Index++, Count++) {\r
- BufferedString[Count] = StringPtr[Index];\r
-\r
- if (IsPassword) {\r
- PrintChar (L'*');\r
- }\r
- }\r
-\r
- if (!IsPassword) {\r
- PrintStringAt (Start + 1, Top + 3, BufferedString);\r
- }\r
- \r
- gST->ConOut->SetAttribute (gST->ConOut, EFI_TEXT_ATTR (EFI_LIGHTGRAY, EFI_BLACK));\r
- gST->ConOut->SetCursorPosition (gST->ConOut, Start + GetStringWidth (StringPtr) / 2, Top + 3);\r
- }\r
- \r
- do {\r
- Status = WaitForKeyStroke (&Key);\r
- ASSERT_EFI_ERROR (Status);\r
-\r
- gST->ConOut->SetAttribute (gST->ConOut, EFI_TEXT_ATTR (EFI_BLACK, EFI_LIGHTGRAY));\r
- switch (Key.UnicodeChar) {\r
- case CHAR_NULL:\r
- switch (Key.ScanCode) {\r
- case SCAN_LEFT:\r
- if (CurrentCursor > 0) {\r
- CurrentCursor--;\r
- }\r
- break;\r
-\r
- case SCAN_RIGHT:\r
- if (CurrentCursor < (GetStringWidth (StringPtr) / 2 - 1)) {\r
- CurrentCursor++;\r
- }\r
- break;\r
-\r
- case SCAN_ESC:\r
- FreePool (TempString);\r
- FreePool (BufferedString);\r
- gST->ConOut->SetAttribute (gST->ConOut, EFI_TEXT_ATTR (EFI_LIGHTGRAY, EFI_BLACK));\r
- gST->ConOut->EnableCursor (gST->ConOut, CursorVisible);\r
- return EFI_DEVICE_ERROR;\r
-\r
- default:\r
- break;\r
- }\r
-\r
- break;\r
-\r
- case CHAR_CARRIAGE_RETURN:\r
- if (GetStringWidth (StringPtr) >= ((Minimum + 1) * sizeof (CHAR16))) {\r
-\r
- FreePool (TempString);\r
- FreePool (BufferedString);\r
- gST->ConOut->SetAttribute (gST->ConOut, EFI_TEXT_ATTR (EFI_LIGHTGRAY, EFI_BLACK));\r
- gST->ConOut->EnableCursor (gST->ConOut, CursorVisible);\r
- return EFI_SUCCESS;\r
- } else {\r
- //\r
- // Simply create a popup to tell the user that they had typed in too few characters.\r
- // To save code space, we can then treat this as an error and return back to the menu.\r
- //\r
- do {\r
- CreateDialog (4, TRUE, 0, NULL, &Key, &NullCharacter, gMiniString, gPressEnter, &NullCharacter);\r
- } while (Key.UnicodeChar != CHAR_CARRIAGE_RETURN);\r
-\r
- FreePool (TempString);\r
- FreePool (BufferedString);\r
- gST->ConOut->SetAttribute (gST->ConOut, EFI_TEXT_ATTR (EFI_LIGHTGRAY, EFI_BLACK));\r
- gST->ConOut->EnableCursor (gST->ConOut, CursorVisible);\r
- return EFI_DEVICE_ERROR;\r
- }\r
-\r
- break;\r
-\r
- case CHAR_BACKSPACE:\r
- if (StringPtr[0] != CHAR_NULL && CurrentCursor != 0) {\r
- for (Index = 0; Index < CurrentCursor - 1; Index++) {\r
- TempString[Index] = StringPtr[Index];\r
- }\r
- Count = GetStringWidth (StringPtr) / 2 - 1;\r
- if (Count >= CurrentCursor) {\r
- for (Index = CurrentCursor - 1, Index2 = CurrentCursor; Index2 < Count; Index++, Index2++) {\r
- TempString[Index] = StringPtr[Index2];\r
- }\r
- TempString[Index] = CHAR_NULL;\r
- }\r
- //\r
- // Effectively truncate string by 1 character\r
- //\r
- StrCpy (StringPtr, TempString);\r
- CurrentCursor --;\r
- }\r
-\r
- default:\r
- //\r
- // If it is the beginning of the string, don't worry about checking maximum limits\r
- //\r
- if ((StringPtr[0] == CHAR_NULL) && (Key.UnicodeChar != CHAR_BACKSPACE)) {\r
- StrnCpy (StringPtr, &Key.UnicodeChar, 1);\r
- CurrentCursor++;\r
- } else if ((GetStringWidth (StringPtr) < ((Maximum + 1) * sizeof (CHAR16))) && (Key.UnicodeChar != CHAR_BACKSPACE)) {\r
- KeyPad[0] = Key.UnicodeChar;\r
- KeyPad[1] = CHAR_NULL;\r
- Count = GetStringWidth (StringPtr) / 2 - 1;\r
- if (CurrentCursor < Count) {\r
- for (Index = 0; Index < CurrentCursor; Index++) {\r
- TempString[Index] = StringPtr[Index];\r
- }\r
- TempString[Index] = CHAR_NULL;\r
- StrCat (TempString, KeyPad);\r
- StrCat (TempString, StringPtr + CurrentCursor);\r
- StrCpy (StringPtr, TempString);\r
- } else {\r
- StrCat (StringPtr, KeyPad);\r
- }\r
- CurrentCursor++;\r
- }\r
-\r
- //\r
- // If the width of the input string is now larger than the screen, we nee to\r
- // adjust the index to start printing portions of the string\r
- //\r
- SetUnicodeMem (BufferedString, ScreenSize - 1, L' ');\r
- PrintStringAt (Start + 1, Top + 3, BufferedString);\r
-\r
- if ((GetStringWidth (StringPtr) / 2) > (DimensionsWidth - 2)) {\r
- Index = (GetStringWidth (StringPtr) / 2) - DimensionsWidth + 2;\r
- } else {\r
- Index = 0;\r
- }\r
-\r
- if (IsPassword) {\r
- gST->ConOut->SetCursorPosition (gST->ConOut, Start + 1, Top + 3);\r
- }\r
-\r
- for (Count = 0; Index + 1 < GetStringWidth (StringPtr) / 2; Index++, Count++) {\r
- BufferedString[Count] = StringPtr[Index];\r
-\r
- if (IsPassword) {\r
- PrintChar (L'*');\r
- }\r
- }\r
-\r
- if (!IsPassword) {\r
- PrintStringAt (Start + 1, Top + 3, BufferedString);\r
- }\r
- break;\r
- }\r
-\r
- gST->ConOut->SetAttribute (gST->ConOut, EFI_TEXT_ATTR (EFI_LIGHTGRAY, EFI_BLACK));\r
- gST->ConOut->SetCursorPosition (gST->ConOut, Start + CurrentCursor + 1, Top + 3);\r
- } while (TRUE);\r
-\r
-}\r
-\r
-/**\r
- Adjust the value to the correct one. Rules follow the sample:\r
- like: Year change: 2012.02.29 -> 2013.02.29 -> 2013.02.01\r
- Month change: 2013.03.29 -> 2013.02.29 -> 2013.02.28\r
-\r
- @param Question Pointer to current question.\r
- @param Sequence The sequence of the field in the question.\r
-**/\r
-VOID\r
-AdjustQuestionValue (\r
- IN FORM_BROWSER_STATEMENT *Question,\r
- IN UINT8 Sequence\r
- )\r
-{\r
- UINT8 Month;\r
- UINT16 Year;\r
- UINT8 Maximum;\r
- UINT8 Minimum;\r
-\r
- if (Question->Operand != EFI_IFR_DATE_OP) {\r
- return;\r
- }\r
-\r
- Month = Question->HiiValue.Value.date.Month;\r
- Year = Question->HiiValue.Value.date.Year;\r
- Minimum = 1;\r
-\r
- switch (Month) {\r
- case 2:\r
- if ((Year % 4) == 0 && ((Year % 100) != 0 || (Year % 400) == 0)) {\r
- Maximum = 29;\r
- } else {\r
- Maximum = 28;\r
- }\r
- break;\r
- case 4:\r
- case 6:\r
- case 9:\r
- case 11:\r
- Maximum = 30;\r
- break;\r
- default:\r
- Maximum = 31;\r
- break;\r
- }\r
-\r
- //\r
- // Change the month area.\r
- //\r
- if (Sequence == 0) {\r
- if (Question->HiiValue.Value.date.Day > Maximum) {\r
- Question->HiiValue.Value.date.Day = Maximum;\r
- }\r
- }\r
- \r
- //\r
- // Change the Year area.\r
- //\r
- if (Sequence == 2) {\r
- if (Question->HiiValue.Value.date.Day > Maximum) {\r
- Question->HiiValue.Value.date.Day = Minimum;\r
- }\r
- }\r
-}\r
-\r
-/**\r
- This routine reads a numeric value from the user input.\r
-\r
- @param Selection Pointer to current selection.\r
- @param MenuOption Pointer to the current input menu.\r
-\r
- @retval EFI_SUCCESS If numerical input is read successfully\r
- @retval EFI_DEVICE_ERROR If operation fails\r
-\r
-**/\r
-EFI_STATUS\r
-GetNumericInput (\r
- IN UI_MENU_SELECTION *Selection,\r
- IN UI_MENU_OPTION *MenuOption\r
- )\r
-{\r
- EFI_STATUS Status;\r
- UINTN Column;\r
- UINTN Row;\r
- CHAR16 InputText[MAX_NUMERIC_INPUT_WIDTH];\r
- CHAR16 FormattedNumber[MAX_NUMERIC_INPUT_WIDTH - 1];\r
- UINT64 PreviousNumber[MAX_NUMERIC_INPUT_WIDTH - 3];\r
- UINTN Count;\r
- UINTN Loop;\r
- BOOLEAN ManualInput;\r
- BOOLEAN HexInput;\r
- BOOLEAN DateOrTime;\r
- UINTN InputWidth;\r
- UINT64 EditValue;\r
- UINT64 Step;\r
- UINT64 Minimum;\r
- UINT64 Maximum;\r
- UINTN EraseLen;\r
- UINT8 Digital;\r
- EFI_INPUT_KEY Key;\r
- EFI_HII_VALUE *QuestionValue;\r
- FORM_BROWSER_FORM *Form;\r
- FORM_BROWSER_FORMSET *FormSet;\r
- FORM_BROWSER_STATEMENT *Question;\r
-\r
- Column = MenuOption->OptCol;\r
- Row = MenuOption->Row;\r
- PreviousNumber[0] = 0;\r
- Count = 0;\r
- InputWidth = 0;\r
- Digital = 0;\r
-\r
- FormSet = Selection->FormSet;\r
- Form = Selection->Form;\r
- Question = MenuOption->ThisTag;\r
- QuestionValue = &Question->HiiValue;\r
- Step = Question->Step;\r
- Minimum = Question->Minimum;\r
- Maximum = Question->Maximum;\r
-\r
- //\r
- // Only two case, user can enter to this function: Enter and +/- case.\r
- // In Enter case, gDirection = 0; in +/- case, gDirection = SCAN_LEFT/SCAN_WRIGHT\r
- //\r
- ManualInput = (BOOLEAN)(gDirection == 0 ? TRUE : FALSE);\r
-\r
- if ((Question->Operand == EFI_IFR_DATE_OP) || (Question->Operand == EFI_IFR_TIME_OP)) {\r
- DateOrTime = TRUE;\r
- } else {\r
- DateOrTime = FALSE;\r
- }\r
-\r
- //\r
- // Prepare Value to be edit\r
- //\r
- EraseLen = 0;\r
- EditValue = 0;\r
- if (Question->Operand == EFI_IFR_DATE_OP) {\r
- Step = 1;\r
- Minimum = 1;\r
-\r
- switch (MenuOption->Sequence) {\r
- case 0:\r
- Maximum = 12;\r
- EraseLen = 4;\r
- EditValue = QuestionValue->Value.date.Month;\r
- break;\r
-\r
- case 1:\r
- switch (QuestionValue->Value.date.Month) {\r
- case 2:\r
- if ((QuestionValue->Value.date.Year % 4) == 0 && \r
- ((QuestionValue->Value.date.Year % 100) != 0 || \r
- (QuestionValue->Value.date.Year % 400) == 0)) {\r
- Maximum = 29;\r
- } else {\r
- Maximum = 28;\r
- }\r
- break;\r
- case 4:\r
- case 6:\r
- case 9:\r
- case 11:\r
- Maximum = 30;\r
- break;\r
- default:\r
- Maximum = 31;\r
- break;\r
- } \r
-\r
- EraseLen = 3;\r
- EditValue = QuestionValue->Value.date.Day;\r
- break;\r
-\r
- case 2:\r
- Maximum = 0xffff;\r
- EraseLen = 5;\r
- EditValue = QuestionValue->Value.date.Year;\r
- break;\r
-\r
- default:\r
- break;\r
- }\r
- } else if (Question->Operand == EFI_IFR_TIME_OP) {\r
- Step = 1;\r
- Minimum = 0;\r
-\r
- switch (MenuOption->Sequence) {\r
- case 0:\r
- Maximum = 23;\r
- EraseLen = 4;\r
- EditValue = QuestionValue->Value.time.Hour;\r
- break;\r
-\r
- case 1:\r
- Maximum = 59;\r
- EraseLen = 3;\r
- EditValue = QuestionValue->Value.time.Minute;\r
- break;\r
-\r
- case 2:\r
- Maximum = 59;\r
- EraseLen = 3;\r
- EditValue = QuestionValue->Value.time.Second;\r
- break;\r
-\r
- default:\r
- break;\r
- }\r
- } else {\r
- //\r
- // Numeric\r
- //\r
- EraseLen = gOptionBlockWidth;\r
- EditValue = QuestionValue->Value.u64;\r
- if (Maximum == 0) {\r
- Maximum = (UINT64) -1;\r
- }\r
- }\r
-\r
- if ((Question->Operand == EFI_IFR_NUMERIC_OP) &&\r
- ((Question->Flags & EFI_IFR_DISPLAY) == EFI_IFR_DISPLAY_UINT_HEX)) {\r
- HexInput = TRUE;\r
- } else {\r
- HexInput = FALSE;\r
- }\r
-\r
- //\r
- // Enter from "Enter" input, clear the old word showing.\r
- //\r
- if (ManualInput) {\r
- if (Question->Operand == EFI_IFR_NUMERIC_OP) {\r
- if (HexInput) {\r
- InputWidth = Question->StorageWidth * 2;\r
- } else {\r
- switch (Question->StorageWidth) {\r
- case 1:\r
- InputWidth = 3;\r
- break;\r
-\r
- case 2:\r
- InputWidth = 5;\r
- break;\r
-\r
- case 4:\r
- InputWidth = 10;\r
- break;\r
-\r
- case 8:\r
- InputWidth = 20;\r
- break;\r
-\r
- default:\r
- InputWidth = 0;\r
- break;\r
- }\r
- }\r
-\r
- InputText[0] = LEFT_NUMERIC_DELIMITER;\r
- SetUnicodeMem (InputText + 1, InputWidth, L' ');\r
- ASSERT (InputWidth + 2 < MAX_NUMERIC_INPUT_WIDTH);\r
- InputText[InputWidth + 1] = RIGHT_NUMERIC_DELIMITER;\r
- InputText[InputWidth + 2] = L'\0';\r
-\r
- PrintAt (Column, Row, InputText);\r
- Column++;\r
- }\r
-\r
- if (Question->Operand == EFI_IFR_DATE_OP) {\r
- if (MenuOption->Sequence == 2) {\r
- InputWidth = 4;\r
- } else {\r
- InputWidth = 2;\r
- }\r
-\r
- if (MenuOption->Sequence == 0) {\r
- InputText[0] = LEFT_NUMERIC_DELIMITER;\r
- SetUnicodeMem (InputText + 1, InputWidth, L' ');\r
- } else {\r
- SetUnicodeMem (InputText, InputWidth, L' ');\r
- }\r
-\r
- if (MenuOption->Sequence == 2) {\r
- InputText[InputWidth + 1] = RIGHT_NUMERIC_DELIMITER;\r
- } else {\r
- InputText[InputWidth + 1] = DATE_SEPARATOR;\r
- }\r
- InputText[InputWidth + 2] = L'\0';\r
-\r
- PrintAt (Column, Row, InputText);\r
- if (MenuOption->Sequence == 0) {\r
- Column++;\r
- }\r
- }\r
-\r
- if (Question->Operand == EFI_IFR_TIME_OP) {\r
- InputWidth = 2;\r
-\r
- if (MenuOption->Sequence == 0) {\r
- InputText[0] = LEFT_NUMERIC_DELIMITER;\r
- SetUnicodeMem (InputText + 1, InputWidth, L' ');\r
- } else {\r
- SetUnicodeMem (InputText, InputWidth, L' ');\r
- }\r
-\r
- if (MenuOption->Sequence == 2) {\r
- InputText[InputWidth + 1] = RIGHT_NUMERIC_DELIMITER;\r
- } else {\r
- InputText[InputWidth + 1] = TIME_SEPARATOR;\r
- }\r
- InputText[InputWidth + 2] = L'\0';\r
-\r
- PrintAt (Column, Row, InputText);\r
- if (MenuOption->Sequence == 0) {\r
- Column++;\r
- }\r
- }\r
- }\r
-\r
- //\r
- // First time we enter this handler, we need to check to see if\r
- // we were passed an increment or decrement directive\r
- //\r
- do {\r
- Key.UnicodeChar = CHAR_NULL;\r
- if (gDirection != 0) {\r
- Key.ScanCode = gDirection;\r
- gDirection = 0;\r
- goto TheKey2;\r
- }\r
-\r
- Status = WaitForKeyStroke (&Key);\r
-\r
-TheKey2:\r
- switch (Key.UnicodeChar) {\r
-\r
- case '+':\r
- case '-':\r
- if (Key.UnicodeChar == '+') {\r
- Key.ScanCode = SCAN_RIGHT;\r
- } else {\r
- Key.ScanCode = SCAN_LEFT;\r
- }\r
- Key.UnicodeChar = CHAR_NULL;\r
- goto TheKey2;\r
-\r
- case CHAR_NULL:\r
- switch (Key.ScanCode) {\r
- case SCAN_LEFT:\r
- case SCAN_RIGHT:\r
- if (DateOrTime && !ManualInput) {\r
- //\r
- // By setting this value, we will return back to the caller.\r
- // We need to do this since an auto-refresh will destroy the adjustment\r
- // based on what the real-time-clock is showing. So we always commit\r
- // upon changing the value.\r
- //\r
- gDirection = SCAN_DOWN;\r
- }\r
-\r
- if ((Step != 0) && !ManualInput) {\r
- if (Key.ScanCode == SCAN_LEFT) {\r
- if (EditValue >= Minimum + Step) {\r
- EditValue = EditValue - Step;\r
- } else if (EditValue > Minimum){\r
- EditValue = Minimum;\r
- } else {\r
- EditValue = Maximum;\r
- }\r
- } else if (Key.ScanCode == SCAN_RIGHT) {\r
- if (EditValue + Step <= Maximum) {\r
- EditValue = EditValue + Step;\r
- } else if (EditValue < Maximum) {\r
- EditValue = Maximum;\r
- } else {\r
- EditValue = Minimum;\r
- }\r
- }\r
-\r
- ZeroMem (FormattedNumber, 21 * sizeof (CHAR16));\r
- if (Question->Operand == EFI_IFR_DATE_OP) {\r
- if (MenuOption->Sequence == 2) {\r
- //\r
- // Year\r
- //\r
- UnicodeSPrint (FormattedNumber, 21 * sizeof (CHAR16), L"%04d", (UINT16) EditValue);\r
- } else {\r
- //\r
- // Month/Day\r
- //\r
- UnicodeSPrint (FormattedNumber, 21 * sizeof (CHAR16), L"%02d", (UINT8) EditValue);\r
- }\r
-\r
- if (MenuOption->Sequence == 0) {\r
- ASSERT (EraseLen >= 2);\r
- FormattedNumber[EraseLen - 2] = DATE_SEPARATOR;\r
- } else if (MenuOption->Sequence == 1) {\r
- ASSERT (EraseLen >= 1);\r
- FormattedNumber[EraseLen - 1] = DATE_SEPARATOR;\r
- }\r
- } else if (Question->Operand == EFI_IFR_TIME_OP) {\r
- UnicodeSPrint (FormattedNumber, 21 * sizeof (CHAR16), L"%02d", (UINT8) EditValue);\r
-\r
- if (MenuOption->Sequence == 0) {\r
- ASSERT (EraseLen >= 2);\r
- FormattedNumber[EraseLen - 2] = TIME_SEPARATOR;\r
- } else if (MenuOption->Sequence == 1) {\r
- ASSERT (EraseLen >= 1);\r
- FormattedNumber[EraseLen - 1] = TIME_SEPARATOR;\r
- }\r
- } else {\r
- QuestionValue->Value.u64 = EditValue;\r
- PrintFormattedNumber (Question, FormattedNumber, 21 * sizeof (CHAR16));\r
- }\r
-\r
- gST->ConOut->SetAttribute (gST->ConOut, PcdGet8 (PcdBrowserFieldTextColor) | FIELD_BACKGROUND);\r
- for (Loop = 0; Loop < EraseLen; Loop++) {\r
- PrintAt (MenuOption->OptCol + Loop, MenuOption->Row, L" ");\r
- }\r
- gST->ConOut->SetAttribute (gST->ConOut, PcdGet8 (PcdBrowserFieldTextHighlightColor) | PcdGet8 (PcdBrowserFieldBackgroundHighlightColor));\r
-\r
- if (MenuOption->Sequence == 0) {\r
- PrintCharAt (MenuOption->OptCol, Row, LEFT_NUMERIC_DELIMITER);\r
- Column = MenuOption->OptCol + 1;\r
- }\r
-\r
- PrintStringAt (Column, Row, FormattedNumber);\r
-\r
- if (!DateOrTime || MenuOption->Sequence == 2) {\r
- PrintChar (RIGHT_NUMERIC_DELIMITER);\r
- }\r
- }\r
-\r
- goto EnterCarriageReturn;\r
- break;\r
-\r
- case SCAN_UP:\r
- case SCAN_DOWN:\r
- goto EnterCarriageReturn;\r
-\r
- case SCAN_ESC:\r
- return EFI_DEVICE_ERROR;\r
-\r
- default:\r
- break;\r
- }\r
-\r
- break;\r
-\r
-EnterCarriageReturn:\r
-\r
- case CHAR_CARRIAGE_RETURN:\r
- //\r
- // Validate input value with Minimum value.\r
- //\r
- if (EditValue < Minimum) {\r
- UpdateStatusBar (Selection, INPUT_ERROR, Question->QuestionFlags, TRUE);\r
- break;\r
- } else {\r
- UpdateStatusBar (Selection, INPUT_ERROR, Question->QuestionFlags, FALSE);\r
- }\r
-\r
- //\r
- // Store Edit value back to Question\r
- //\r
- if (Question->Operand == EFI_IFR_DATE_OP) {\r
- switch (MenuOption->Sequence) {\r
- case 0:\r
- QuestionValue->Value.date.Month = (UINT8) EditValue;\r
- break;\r
-\r
- case 1:\r
- QuestionValue->Value.date.Day = (UINT8) EditValue;\r
- break;\r
-\r
- case 2:\r
- QuestionValue->Value.date.Year = (UINT16) EditValue;\r
- break;\r
-\r
- default:\r
- break;\r
- }\r
- } else if (Question->Operand == EFI_IFR_TIME_OP) {\r
- switch (MenuOption->Sequence) {\r
- case 0:\r
- QuestionValue->Value.time.Hour = (UINT8) EditValue;\r
- break;\r
-\r
- case 1:\r
- QuestionValue->Value.time.Minute = (UINT8) EditValue;\r
- break;\r
-\r
- case 2:\r
- QuestionValue->Value.time.Second = (UINT8) EditValue;\r
- break;\r
-\r
- default:\r
- break;\r
- }\r
- } else {\r
- //\r
- // Numeric\r
- //\r
- QuestionValue->Value.u64 = EditValue;\r
- }\r
-\r
- //\r
- // Adjust the value to the correct one.\r
- // Sample like: 2012.02.29 -> 2013.02.29 -> 2013.02.01\r
- // 2013.03.29 -> 2013.02.29 -> 2013.02.28\r
- //\r
- if (Question->Operand == EFI_IFR_DATE_OP && \r
- (MenuOption->Sequence == 0 || MenuOption->Sequence == 2)) {\r
- AdjustQuestionValue (Question, (UINT8)MenuOption->Sequence);\r
- }\r
-\r
- //\r
- // Check to see if the Value is something reasonable against consistency limitations.\r
- // If not, let's kick the error specified.\r
- //\r
- Status = ValidateQuestion (FormSet, Form, Question, EFI_HII_EXPRESSION_INCONSISTENT_IF);\r
- if (EFI_ERROR (Status)) {\r
- //\r
- // Input value is not valid, restore Question Value\r
- //\r
- GetQuestionValue (FormSet, Form, Question, GetSetValueWithEditBuffer);\r
- } else {\r
- SetQuestionValue (FormSet, Form, Question, GetSetValueWithEditBuffer);\r
- if (!DateOrTime || (Question->Storage != NULL)) {\r
- //\r
- // NV flag is unnecessary for RTC type of Date/Time\r
- //\r
- UpdateStatusBar (Selection, NV_UPDATE_REQUIRED, Question->QuestionFlags, TRUE);\r
- }\r
- }\r
-\r
- return Status;\r
- break;\r
-\r
- case CHAR_BACKSPACE:\r
- if (ManualInput) {\r
- if (Count == 0) {\r
- break;\r
- }\r
- //\r
- // Remove a character\r
- //\r
- EditValue = PreviousNumber[Count - 1];\r
- UpdateStatusBar (Selection, INPUT_ERROR, Question->QuestionFlags, FALSE);\r
- Count--;\r
- Column--;\r
- PrintAt (Column, Row, L" ");\r
- }\r
- break;\r
-\r
- default:\r
- if (ManualInput) {\r
- if (HexInput) {\r
- if ((Key.UnicodeChar >= L'0') && (Key.UnicodeChar <= L'9')) {\r
- Digital = (UINT8) (Key.UnicodeChar - L'0');\r
- } else if ((Key.UnicodeChar >= L'A') && (Key.UnicodeChar <= L'F')) {\r
- Digital = (UINT8) (Key.UnicodeChar - L'A' + 0x0A);\r
- } else if ((Key.UnicodeChar >= L'a') && (Key.UnicodeChar <= L'f')) {\r
- Digital = (UINT8) (Key.UnicodeChar - L'a' + 0x0A);\r
- } else {\r
- UpdateStatusBar (Selection, INPUT_ERROR, Question->QuestionFlags, TRUE);\r
- break;\r
- }\r
- } else {\r
- if (Key.UnicodeChar > L'9' || Key.UnicodeChar < L'0') {\r
- UpdateStatusBar (Selection, INPUT_ERROR, Question->QuestionFlags, TRUE);\r
- break;\r
- }\r
- }\r
-\r
- //\r
- // If Count exceed input width, there is no way more is valid\r
- //\r
- if (Count >= InputWidth) {\r
- break;\r
- }\r
- //\r
- // Someone typed something valid!\r
- //\r
- if (Count != 0) {\r
- if (HexInput) {\r
- EditValue = LShiftU64 (EditValue, 4) + Digital;\r
- } else {\r
- EditValue = MultU64x32 (EditValue, 10) + (Key.UnicodeChar - L'0');\r
- }\r
- } else {\r
- if (HexInput) {\r
- EditValue = Digital;\r
- } else {\r
- EditValue = Key.UnicodeChar - L'0';\r
- }\r
- }\r
-\r
- if (EditValue > Maximum) {\r
- UpdateStatusBar (Selection, INPUT_ERROR, Question->QuestionFlags, TRUE);\r
- ASSERT (Count < sizeof (PreviousNumber) / sizeof (PreviousNumber[0]));\r
- EditValue = PreviousNumber[Count];\r
- break;\r
- } else {\r
- UpdateStatusBar (Selection, INPUT_ERROR, Question->QuestionFlags, FALSE);\r
- }\r
-\r
- Count++;\r
- ASSERT (Count < (sizeof (PreviousNumber) / sizeof (PreviousNumber[0])));\r
- PreviousNumber[Count] = EditValue;\r
-\r
- PrintCharAt (Column, Row, Key.UnicodeChar);\r
- Column++;\r
- }\r
- break;\r
- }\r
- } while (TRUE);\r
-\r
-}\r
-\r
-\r
-/**\r
- Get selection for OneOf and OrderedList (Left/Right will be ignored).\r
-\r
- @param Selection Pointer to current selection.\r
- @param MenuOption Pointer to the current input menu.\r
-\r
- @retval EFI_SUCCESS If Option input is processed successfully\r
- @retval EFI_DEVICE_ERROR If operation fails\r
-\r
-**/\r
-EFI_STATUS\r
-GetSelectionInputPopUp (\r
- IN UI_MENU_SELECTION *Selection,\r
- IN UI_MENU_OPTION *MenuOption\r
- )\r
-{\r
- EFI_STATUS Status;\r
- EFI_INPUT_KEY Key;\r
- UINTN Index;\r
- CHAR16 *StringPtr;\r
- CHAR16 *TempStringPtr;\r
- UINTN Index2;\r
- UINTN TopOptionIndex;\r
- UINTN HighlightOptionIndex;\r
- UINTN Start;\r
- UINTN End;\r
- UINTN Top;\r
- UINTN Bottom;\r
- UINTN PopUpMenuLines;\r
- UINTN MenuLinesInView;\r
- UINTN PopUpWidth;\r
- CHAR16 Character;\r
- INT32 SavedAttribute;\r
- BOOLEAN ShowDownArrow;\r
- BOOLEAN ShowUpArrow;\r
- UINTN DimensionsWidth;\r
- LIST_ENTRY *Link;\r
- BOOLEAN OrderedList;\r
- UINT8 *ValueArray;\r
- UINT8 ValueType;\r
- EFI_HII_VALUE HiiValue;\r
- EFI_HII_VALUE *HiiValueArray;\r
- UINTN OptionCount;\r
- QUESTION_OPTION *OneOfOption;\r
- QUESTION_OPTION *CurrentOption;\r
- FORM_BROWSER_STATEMENT *Question;\r
- INTN Result;\r
-\r
- DimensionsWidth = gScreenDimensions.RightColumn - gScreenDimensions.LeftColumn;\r
-\r
- ValueArray = NULL;\r
- ValueType = 0;\r
- CurrentOption = NULL;\r
- ShowDownArrow = FALSE;\r
- ShowUpArrow = FALSE;\r
-\r
- StringPtr = AllocateZeroPool ((gOptionBlockWidth + 1) * 2);\r
- ASSERT (StringPtr);\r
-\r
- Question = MenuOption->ThisTag;\r
- if (Question->Operand == EFI_IFR_ORDERED_LIST_OP) {\r
- ValueArray = Question->BufferValue;\r
- ValueType = Question->ValueType;\r
- OrderedList = TRUE;\r
- } else {\r
- OrderedList = FALSE;\r
- }\r
-\r
- //\r
- // Calculate Option count\r
- //\r
- if (OrderedList) {\r
- for (Index = 0; Index < Question->MaxContainers; Index++) {\r
- if (GetArrayData (ValueArray, ValueType, Index) == 0) {\r
- break;\r
- }\r
- }\r
-\r
- OptionCount = Index;\r
- } else {\r
- OptionCount = 0;\r
- Link = GetFirstNode (&Question->OptionListHead);\r
- while (!IsNull (&Question->OptionListHead, Link)) {\r
- OneOfOption = QUESTION_OPTION_FROM_LINK (Link);\r
-\r
- OptionCount++;\r
-\r
- Link = GetNextNode (&Question->OptionListHead, Link);\r
- }\r
- }\r
-\r
- //\r
- // Move valid Option to list head.\r
- //\r
- PopUpMenuLines = 0;\r
- if (OrderedList) {\r
- //\r
- // Prepare HiiValue array\r
- // \r
- HiiValueArray = AllocateZeroPool (OptionCount * sizeof (EFI_HII_VALUE));\r
- ASSERT (HiiValueArray != NULL);\r
- for (Index = 0; Index < OptionCount; Index++) {\r
- HiiValueArray[Index].Type = ValueType;\r
- HiiValueArray[Index].Value.u64 = GetArrayData (ValueArray, ValueType, Index);\r
- }\r
-\r
- for (Index = 0; Index < OptionCount; Index++) {\r
- OneOfOption = ValueToOption (Question, &HiiValueArray[OptionCount - Index - 1]);\r
- if (OneOfOption == NULL) {\r
- return EFI_NOT_FOUND;\r
- }\r
-\r
- RemoveEntryList (&OneOfOption->Link);\r
-\r
- //\r
- // Insert to head.\r
- //\r
- InsertHeadList (&Question->OptionListHead, &OneOfOption->Link);\r
-\r
- PopUpMenuLines++;\r
- }\r
-\r
- FreePool (HiiValueArray);\r
- } else {\r
- Link = GetFirstNode (&Question->OptionListHead);\r
- for (Index = 0; Index < OptionCount; Index++) {\r
- OneOfOption = QUESTION_OPTION_FROM_LINK (Link);\r
- Link = GetNextNode (&Question->OptionListHead, Link);\r
- if ((OneOfOption->SuppressExpression != NULL) &&\r
- EvaluateExpressionList(OneOfOption->SuppressExpression, FALSE, NULL, NULL) > ExpressFalse) {\r
- continue;\r
- } else {\r
- PopUpMenuLines++;\r
- }\r
- }\r
- }\r
-\r
- //\r
- // Get the number of one of options present and its size\r
- //\r
- PopUpWidth = 0;\r
- HighlightOptionIndex = 0;\r
- Link = GetFirstNode (&Question->OptionListHead);\r
- for (Index = 0; Index < PopUpMenuLines; Index++) {\r
- OneOfOption = QUESTION_OPTION_FROM_LINK (Link);\r
- Link = GetNextNode (&Question->OptionListHead, Link);\r
-\r
- if (!OrderedList && (OneOfOption->SuppressExpression != NULL) &&\r
- EvaluateExpressionList(OneOfOption->SuppressExpression, FALSE, NULL, NULL) > ExpressFalse) {\r
- Index--;\r
- continue;\r
- }\r
-\r
- StringPtr = GetToken (OneOfOption->Text, MenuOption->Handle);\r
- if (StrLen (StringPtr) > PopUpWidth) {\r
- PopUpWidth = StrLen (StringPtr);\r
- }\r
- FreePool (StringPtr);\r
-\r
- if (!OrderedList && (CompareHiiValue (&Question->HiiValue, &OneOfOption->Value, &Result, NULL) == EFI_SUCCESS) && (Result == 0)) {\r
- //\r
- // Find current selected Option for OneOf\r
- //\r
- HighlightOptionIndex = Index;\r
- }\r
- }\r
-\r
- //\r
- // Perform popup menu initialization.\r
- //\r
- PopUpWidth = PopUpWidth + POPUP_PAD_SPACE_COUNT;\r
-\r
- SavedAttribute = gST->ConOut->Mode->Attribute;\r
- gST->ConOut->SetAttribute (gST->ConOut, POPUP_TEXT | POPUP_BACKGROUND);\r
-\r
- if ((PopUpWidth + POPUP_FRAME_WIDTH) > DimensionsWidth) {\r
- PopUpWidth = DimensionsWidth - POPUP_FRAME_WIDTH;\r
- }\r
-\r
- Start = (DimensionsWidth - PopUpWidth - POPUP_FRAME_WIDTH) / 2 + gScreenDimensions.LeftColumn;\r
- End = Start + PopUpWidth + POPUP_FRAME_WIDTH;\r
- Top = gScreenDimensions.TopRow + NONE_FRONT_PAGE_HEADER_HEIGHT;\r
- Bottom = gScreenDimensions.BottomRow - STATUS_BAR_HEIGHT - gFooterHeight - 1;\r
-\r
- MenuLinesInView = Bottom - Top - 1;\r
- if (MenuLinesInView >= PopUpMenuLines) {\r
- Top = Top + (MenuLinesInView - PopUpMenuLines) / 2;\r
- Bottom = Top + PopUpMenuLines + 1;\r
- } else {\r
- ShowDownArrow = TRUE;\r
- }\r
-\r
- if (HighlightOptionIndex > (MenuLinesInView - 1)) {\r
- TopOptionIndex = HighlightOptionIndex - MenuLinesInView + 1;\r
- } else {\r
- TopOptionIndex = 0;\r
- }\r
-\r
- do {\r
- //\r
- // Clear that portion of the screen\r
- //\r
- ClearLines (Start, End, Top, Bottom, POPUP_TEXT | POPUP_BACKGROUND);\r
-\r
- //\r
- // Draw "One of" pop-up menu\r
- //\r
- Character = BOXDRAW_DOWN_RIGHT;\r
- PrintCharAt (Start, Top, Character);\r
- for (Index = Start; Index + 2 < End; Index++) {\r
- if ((ShowUpArrow) && ((Index + 1) == (Start + End) / 2)) {\r
- Character = GEOMETRICSHAPE_UP_TRIANGLE;\r
- } else {\r
- Character = BOXDRAW_HORIZONTAL;\r
- }\r
-\r
- PrintChar (Character);\r
- }\r
-\r
- Character = BOXDRAW_DOWN_LEFT;\r
- PrintChar (Character);\r
- Character = BOXDRAW_VERTICAL;\r
- for (Index = Top + 1; Index < Bottom; Index++) {\r
- PrintCharAt (Start, Index, Character);\r
- PrintCharAt (End - 1, Index, Character);\r
- }\r
-\r
- //\r
- // Move to top Option\r
- //\r
- Link = GetFirstNode (&Question->OptionListHead);\r
- for (Index = 0; Index < TopOptionIndex; Index++) {\r
- Link = GetNextNode (&Question->OptionListHead, Link);\r
-\r
- OneOfOption = QUESTION_OPTION_FROM_LINK (Link);\r
- if (!OrderedList && (OneOfOption->SuppressExpression != NULL) &&\r
- EvaluateExpressionList(OneOfOption->SuppressExpression, FALSE, NULL, NULL) > ExpressFalse) {\r
- Index--;\r
- continue;\r
- }\r
- }\r
-\r
- //\r
- // Display the One of options\r
- //\r
- Index2 = Top + 1;\r
- for (Index = TopOptionIndex; (Index < PopUpMenuLines) && (Index2 < Bottom); Index++) {\r
- OneOfOption = QUESTION_OPTION_FROM_LINK (Link);\r
- Link = GetNextNode (&Question->OptionListHead, Link);\r
-\r
- if (!OrderedList && (OneOfOption->SuppressExpression != NULL) &&\r
- EvaluateExpressionList(OneOfOption->SuppressExpression, FALSE, NULL, NULL) > ExpressFalse) {\r
- Index--;\r
- continue;\r
- }\r
-\r
- StringPtr = GetToken (OneOfOption->Text, MenuOption->Handle);\r
- ASSERT (StringPtr != NULL);\r
- //\r
- // If the string occupies multiple lines, truncate it to fit in one line,\r
- // and append a "..." for indication.\r
- //\r
- if (StrLen (StringPtr) > (PopUpWidth - 1)) {\r
- TempStringPtr = AllocateZeroPool (sizeof (CHAR16) * (PopUpWidth - 1));\r
- ASSERT ( TempStringPtr != NULL );\r
- CopyMem (TempStringPtr, StringPtr, (sizeof (CHAR16) * (PopUpWidth - 5)));\r
- FreePool (StringPtr);\r
- StringPtr = TempStringPtr;\r
- StrCat (StringPtr, L"...");\r
- }\r
-\r
- if (Index == HighlightOptionIndex) {\r
- //\r
- // Highlight the selected one\r
- //\r
- CurrentOption = OneOfOption;\r
-\r
- gST->ConOut->SetAttribute (gST->ConOut, PICKLIST_HIGHLIGHT_TEXT | PICKLIST_HIGHLIGHT_BACKGROUND);\r
- PrintStringAt (Start + 2, Index2, StringPtr);\r
- gST->ConOut->SetAttribute (gST->ConOut, POPUP_TEXT | POPUP_BACKGROUND);\r
- } else {\r
- gST->ConOut->SetAttribute (gST->ConOut, POPUP_TEXT | POPUP_BACKGROUND);\r
- PrintStringAt (Start + 2, Index2, StringPtr);\r
- }\r
-\r
- Index2++;\r
- FreePool (StringPtr);\r
- }\r
-\r
- Character = BOXDRAW_UP_RIGHT;\r
- PrintCharAt (Start, Bottom, Character);\r
- for (Index = Start; Index + 2 < End; Index++) {\r
- if ((ShowDownArrow) && ((Index + 1) == (Start + End) / 2)) {\r
- Character = GEOMETRICSHAPE_DOWN_TRIANGLE;\r
- } else {\r
- Character = BOXDRAW_HORIZONTAL;\r
- }\r
-\r
- PrintChar (Character);\r
- }\r
-\r
- Character = BOXDRAW_UP_LEFT;\r
- PrintChar (Character);\r
-\r
- //\r
- // Get User selection\r
- //\r
- Key.UnicodeChar = CHAR_NULL;\r
- if ((gDirection == SCAN_UP) || (gDirection == SCAN_DOWN)) {\r
- Key.ScanCode = gDirection;\r
- gDirection = 0;\r
- goto TheKey;\r
- }\r
-\r
- Status = WaitForKeyStroke (&Key);\r
-\r
-TheKey:\r
- switch (Key.UnicodeChar) {\r
- case '+':\r
- if (OrderedList) {\r
- if ((TopOptionIndex > 0) && (TopOptionIndex == HighlightOptionIndex)) {\r
- //\r
- // Highlight reaches the top of the popup window, scroll one menu item.\r
- //\r
- TopOptionIndex--;\r
- ShowDownArrow = TRUE;\r
- }\r
-\r
- if (TopOptionIndex == 0) {\r
- ShowUpArrow = FALSE;\r
- }\r
-\r
- if (HighlightOptionIndex > 0) {\r
- HighlightOptionIndex--;\r
-\r
- ASSERT (CurrentOption != NULL);\r
- SwapListEntries (CurrentOption->Link.BackLink, &CurrentOption->Link);\r
- }\r
- }\r
- break;\r
-\r
- case '-':\r
- //\r
- // If an ordered list op-code, we will allow for a popup of +/- keys\r
- // to create an ordered list of items\r
- //\r
- if (OrderedList) {\r
- if (((TopOptionIndex + MenuLinesInView) < PopUpMenuLines) &&\r
- (HighlightOptionIndex == (TopOptionIndex + MenuLinesInView - 1))) {\r
- //\r
- // Highlight reaches the bottom of the popup window, scroll one menu item.\r
- //\r
- TopOptionIndex++;\r
- ShowUpArrow = TRUE;\r
- }\r
-\r
- if ((TopOptionIndex + MenuLinesInView) == PopUpMenuLines) {\r
- ShowDownArrow = FALSE;\r
- }\r
-\r
- if (HighlightOptionIndex < (PopUpMenuLines - 1)) {\r
- HighlightOptionIndex++;\r
-\r
- ASSERT (CurrentOption != NULL);\r
- SwapListEntries (&CurrentOption->Link, CurrentOption->Link.ForwardLink);\r
- }\r
- }\r
- break;\r
-\r
- case CHAR_NULL:\r
- switch (Key.ScanCode) {\r
- case SCAN_UP:\r
- case SCAN_DOWN:\r
- if (Key.ScanCode == SCAN_UP) {\r
- if ((TopOptionIndex > 0) && (TopOptionIndex == HighlightOptionIndex)) {\r
- //\r
- // Highlight reaches the top of the popup window, scroll one menu item.\r
- //\r
- TopOptionIndex--;\r
- ShowDownArrow = TRUE;\r
- }\r
-\r
- if (TopOptionIndex == 0) {\r
- ShowUpArrow = FALSE;\r
- }\r
-\r
- if (HighlightOptionIndex > 0) {\r
- HighlightOptionIndex--;\r
- }\r
- } else {\r
- if (((TopOptionIndex + MenuLinesInView) < PopUpMenuLines) &&\r
- (HighlightOptionIndex == (TopOptionIndex + MenuLinesInView - 1))) {\r
- //\r
- // Highlight reaches the bottom of the popup window, scroll one menu item.\r
- //\r
- TopOptionIndex++;\r
- ShowUpArrow = TRUE;\r
- }\r
-\r
- if ((TopOptionIndex + MenuLinesInView) == PopUpMenuLines) {\r
- ShowDownArrow = FALSE;\r
- }\r
-\r
- if (HighlightOptionIndex < (PopUpMenuLines - 1)) {\r
- HighlightOptionIndex++;\r
- }\r
- }\r
- break;\r
-\r
- case SCAN_ESC:\r
- gST->ConOut->SetAttribute (gST->ConOut, SavedAttribute);\r
-\r
- //\r
- // Restore link list order for orderedlist\r
- //\r
- if (OrderedList) {\r
- HiiValue.Type = ValueType;\r
- HiiValue.Value.u64 = 0;\r
- for (Index = 0; Index < Question->MaxContainers; Index++) {\r
- HiiValue.Value.u64 = GetArrayData (ValueArray, ValueType, Index);\r
- if (HiiValue.Value.u64 == 0) {\r
- break;\r
- }\r
-\r
- OneOfOption = ValueToOption (Question, &HiiValue);\r
- if (OneOfOption == NULL) {\r
- return EFI_NOT_FOUND;\r
- }\r
-\r
- RemoveEntryList (&OneOfOption->Link);\r
- InsertTailList (&Question->OptionListHead, &OneOfOption->Link);\r
- }\r
- }\r
-\r
- return EFI_DEVICE_ERROR;\r
-\r
- default:\r
- break;\r
- }\r
-\r
- break;\r
-\r
- case CHAR_CARRIAGE_RETURN:\r
- //\r
- // return the current selection\r
- //\r
- if (OrderedList) {\r
- Index = 0;\r
- Link = GetFirstNode (&Question->OptionListHead);\r
- while (!IsNull (&Question->OptionListHead, Link)) {\r
- OneOfOption = QUESTION_OPTION_FROM_LINK (Link);\r
- Link = GetNextNode (&Question->OptionListHead, Link);\r
-\r
- if ((OneOfOption->SuppressExpression != NULL) &&\r
- EvaluateExpressionList(OneOfOption->SuppressExpression, FALSE, NULL, NULL) != ExpressFalse) {\r
- continue;\r
- }\r
-\r
- SetArrayData (ValueArray, ValueType, Index, OneOfOption->Value.Value.u64);\r
-\r
- Index++;\r
- if (Index > Question->MaxContainers) {\r
- break;\r
- }\r
- }\r
- } else {\r
- ASSERT (CurrentOption != NULL);\r
- CopyMem (&Question->HiiValue, &CurrentOption->Value, sizeof (EFI_HII_VALUE));\r
- }\r
-\r
- gST->ConOut->SetAttribute (gST->ConOut, SavedAttribute);\r
-\r
- Status = ValidateQuestion (Selection->FormSet, Selection->Form, Question, EFI_HII_EXPRESSION_INCONSISTENT_IF);\r
- if (EFI_ERROR (Status)) {\r
- //\r
- // Input value is not valid, restore Question Value\r
- //\r
- GetQuestionValue (Selection->FormSet, Selection->Form, Question, GetSetValueWithEditBuffer);\r
- } else {\r
- SetQuestionValue (Selection->FormSet, Selection->Form, Question, GetSetValueWithEditBuffer);\r
- UpdateStatusBar (Selection, NV_UPDATE_REQUIRED, Question->QuestionFlags, TRUE);\r
- }\r
-\r
- return Status;\r
-\r
- default:\r
- break;\r
- }\r
- } while (TRUE);\r
-\r
-}\r
-\r
-/**\r
- Wait for a key to be pressed by user.\r
-\r
- @param Key The key which is pressed by user.\r
-\r
- @retval EFI_SUCCESS The function always completed successfully.\r
-\r
-**/\r
-EFI_STATUS\r
-WaitForKeyStroke (\r
- OUT EFI_INPUT_KEY *Key\r
- )\r
-{\r
- EFI_STATUS Status;\r
-\r
- while (TRUE) {\r
- Status = gST->ConIn->ReadKeyStroke (gST->ConIn, Key);\r
- if (!EFI_ERROR (Status)) {\r
- break;\r
- }\r
-\r
- if (Status != EFI_NOT_READY) {\r
- continue;\r
- }\r
-\r
- UiWaitForSingleEvent (gST->ConIn->WaitForKey, 0, 0);\r
- }\r
- return Status;\r
-}\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
+ Add empty function for event process function.\r
+\r
+ @param Event The Event need to be process\r
+ @param Context The context of the event.\r
+\r
+**/\r
+VOID\r
+EFIAPI\r
+SetupBrowserEmptyFunction (\r
+ IN EFI_EVENT Event,\r
+ IN VOID *Context\r
+ )\r
+{\r
+}\r
+\r
+/**\r
+ Base on the opcode buffer info to get the display statement.\r
+\r
+ @param OpCode The input opcode buffer for this statement.\r
+ \r
+ @retval Statement The statement use this opcode buffer.\r
+\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
+ 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
+ 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 (EventNode);\r
+ }\r
+}\r
+\r
+/**\r
+ Check whether this statement value is changed. If yes, update the statement value and return TRUE; \r
+ else return FALSE.\r
+\r
+ @param Statement The statement need to check.\r
+\r
+**/\r
+VOID\r
+UpdateStatement (\r
+ IN OUT FORM_BROWSER_STATEMENT *Statement\r
+ )\r
+{\r
+ GetQuestionValue (gCurrentSelection->FormSet, gCurrentSelection->Form, Statement, GetSetValueWithHiiDriver);\r
+\r
+ //\r
+ // Reset FormPackage update flag\r
+ //\r
+ mHiiPackageListUpdated = FALSE;\r
+\r
+ //\r
+ // Question value may be changed, need invoke its Callback()\r
+ //\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
+/**\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
+ Create refresh hook event for statement which has refresh event or interval.\r
+\r
+ @param Statement The statement need to check.\r
+\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
+ //\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
+UINT32\r
+InConsistentIfCheck (\r
+ IN FORM_BROWSER_STATEMENT *Question,\r
+ OUT STATEMENT_ERROR_INFO *ErrorInfo\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ LIST_ENTRY *Link;\r
+ FORM_EXPRESSION *Expression;\r
+ LIST_ENTRY *ListHead;\r
+ UINT32 RetVal;\r
+\r
+ RetVal = STATEMENT_VALID;\r
+ ListHead = &Question->InconsistentListHead;\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
+ // Evaluate the expression\r
+ //\r
+ Status = EvaluateExpression (gCurrentSelection->FormSet, gCurrentSelection->Form, Expression);\r
+ if (EFI_ERROR (Status)) {\r
+ continue;\r
+ }\r
+\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 RetVal;\r
+}\r
+\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
+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
+ 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
+ ASSERT (Form != NULL && Statement != NULL && InputValue != NULL && ErrorInfo != NULL);\r
+\r
+ Question = GetBrowserStatement(Statement);\r
+ ASSERT (Question != NULL);\r
+\r
+ //\r
+ // Back up the quesion value.\r
+ //\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
+ default:\r
+ CopyMem (&BackUpValue, &Question->HiiValue, sizeof (EFI_HII_VALUE));\r
+ CopyMem (&Question->HiiValue, InputValue, sizeof (EFI_HII_VALUE));\r
+ break;\r
+ }\r
+\r
+ //\r
+ // Do the inconsistentif check.\r
+ //\r
+ if (!IsListEmpty (&Question->InconsistentListHead)) {\r
+ RetVal = InConsistentIfCheck(Question, ErrorInfo);\r
+ }\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
+ default:\r
+ CopyMem (&Question->HiiValue, &BackUpValue, sizeof (EFI_HII_VALUE));\r
+ break;\r
+ }\r
+\r
+ return RetVal;\r
+}\r
+\r
+/**\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
+ 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
+ DisplayStatement->CurrentValue.Buffer = AllocateCopyPool(Statement->StorageWidth,Statement->BufferValue);\r
+ DisplayStatement->CurrentValue.BufferLen = Statement->StorageWidth;\r
+ }\r
+\r
+ DisplayStatement->SettingChangedFlag = Statement->ValueChanged;\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
+ //\r
+ // Create the refresh event process function.\r
+ //\r
+ if (!CompareGuid (&Statement->RefreshGuid, &gZeroGuid)) {\r
+ CreateRefreshEvent (Statement);\r
+ }\r
+\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
+ //\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
+ //\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
+ // 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
+ Process for the refresh interval statement.\r
+\r
+ @param Event The Event need to be process\r
+ @param Context The context of the event.\r
+\r
+**/\r
+VOID\r
+EFIAPI\r
+RefreshIntervalProcess (\r
+ IN EFI_EVENT Event,\r
+ IN VOID *Context\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
+ Link = GetNextNode (&gCurrentSelection->Form->StatementListHead, Link);\r
+\r
+ if (Statement->RefreshInterval == 0) {\r
+ continue;\r
+ }\r
+\r
+ UpdateStatement(Statement);\r
+ }\r
+\r
+ gBS->SignalEvent (mValueChangedEvent);\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
- Clear retangle with specified text attribute.\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
+ 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
-ClearLines (\r
- IN UINTN LeftColumn,\r
- IN UINTN RightColumn,\r
- IN UINTN TopRow,\r
- IN UINTN BottomRow,\r
- IN UINTN TextAttribute\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
+ DisplayStatement = AllocateZeroPool (sizeof (FORM_DISPLAY_ENGINE_STATEMENT));\r
+ ASSERT (DisplayStatement != NULL);\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
+ 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
- CHAR16 *Buffer;\r
- UINTN Row;\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
- // For now, allocate an arbitrarily long buffer\r
+ // Retrieve all HII Handles from HII database\r
//\r
- Buffer = AllocateZeroPool (0x10000);\r
- ASSERT (Buffer != NULL);\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
- // Set foreground and background as defined\r
+ // Search Hii Handle by Driver Handle\r
//\r
- gST->ConOut->SetAttribute (gST->ConOut, TextAttribute);\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
- // Much faster to buffer the long string instead of print it a character at a time\r
+ // Get all the Hii handles\r
//\r
- SetUnicodeMem (Buffer, RightColumn - LeftColumn, L' ');\r
+ HiiHandles = HiiGetHiiHandles (NULL);\r
+ ASSERT (HiiHandles != NULL);\r
\r
//\r
- // Clear the desired area with the appropriate foreground/background\r
+ // Search for formset of each class type\r
//\r
- for (Row = TopRow; Row <= BottomRow; Row++) {\r
- PrintStringAt (LeftColumn, Row, Buffer);\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
- gST->ConOut->SetCursorPosition (gST->ConOut, LeftColumn, TopRow);\r
+ FreePool (HiiHandles);\r
\r
- FreePool (Buffer);\r
- return ;\r
+ return HiiHandle;\r
}\r
\r
/**\r
- Concatenate a narrow string to another string.\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 Destination The destination string.\r
- @param Source The source string. The string to be concatenated.\r
- to the end of Destination.\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
-VOID\r
-NewStrCat (\r
- IN OUT CHAR16 *Destination,\r
- IN CHAR16 *Source\r
+BOOLEAN\r
+ProcessChangedData (\r
+ IN OUT UI_MENU_SELECTION *Selection,\r
+ IN BROWSER_SETTING_SCOPE Scope\r
)\r
{\r
- UINTN Length;\r
+ BOOLEAN RetValue;\r
\r
- for (Length = 0; Destination[Length] != 0; Length++)\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
- //\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
- //\r
- Destination[Length] = NARROW_CHAR;\r
- Length++;\r
+ case BROWSER_ACTION_NONE:\r
+ RetValue = FALSE;\r
+ break;\r
\r
- StrCpy (Destination + Length, Source);\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
- Count the storage space of a Unicode string.\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
-\r
- If String is NULL, then ASSERT ().\r
-\r
- @param String The input string to be counted.\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
- @return Storage space for the input string.\r
+ @param Selection The selection info.\r
\r
**/\r
-UINTN\r
-GetStringWidth (\r
- IN CHAR16 *String\r
+VOID\r
+FindParentFormSet (\r
+ IN OUT UI_MENU_SELECTION *Selection\r
)\r
{\r
- UINTN Index;\r
- UINTN Count;\r
- UINTN IncrementValue;\r
-\r
- ASSERT (String != NULL);\r
- if (String == NULL) {\r
- return 0;\r
- }\r
-\r
- Index = 0;\r
- Count = 0;\r
- IncrementValue = 1;\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
+ FORM_ENTRY_INFO *CurrentMenu;\r
+ FORM_ENTRY_INFO *ParentMenu;\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
- //\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
- }\r
- } while (String[Index] != 0);\r
+ CurrentMenu = Selection->CurrentMenu;\r
+ ParentMenu = UiFindParentMenu(CurrentMenu);\r
\r
//\r
- // Increment by one to include the null-terminator in the size\r
+ // Find a menu which has different formset guid with current.\r
//\r
- Count++;\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
- return Count * sizeof (CHAR16);\r
+ Selection->Statement = NULL;\r
}\r
\r
/**\r
- This function displays the page frame.\r
+ Process the goto op code, update the info in the selection structure.\r
\r
- @param Selection Selection contains the information about \r
- the Selection, form and formset to be displayed.\r
- Selection action may be updated in retrieve callback.\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
-VOID\r
-DisplayPageFrame (\r
- IN UI_MENU_SELECTION *Selection\r
+EFI_STATUS\r
+ProcessGotoOpCode (\r
+ IN OUT FORM_BROWSER_STATEMENT *Statement,\r
+ IN OUT UI_MENU_SELECTION *Selection\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
-\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
-\r
- if (Selection->Form->ModalForm) {\r
- return;\r
- }\r
-\r
- CopyMem (&LocalScreen, &gScreenDimensions, sizeof (EFI_SCREEN_DESCRIPTOR));\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
- // For now, allocate an arbitrarily long buffer\r
+ // Prepare the device path check, get the device path info first.\r
//\r
- Buffer = AllocateZeroPool (0x10000);\r
- ASSERT (Buffer != NULL);\r
-\r
- Character = BOXDRAW_HORIZONTAL;\r
-\r
- for (Index = 0; Index + 2 < (LocalScreen.RightColumn - LocalScreen.LeftColumn); Index++) {\r
- Buffer[Index] = Character;\r
+ if (Statement->HiiValue.Value.ref.DevicePath != 0) {\r
+ StringPtr = GetToken (Statement->HiiValue.Value.ref.DevicePath, Selection->FormSet->HiiHandle);\r
}\r
\r
- if ((gClassOfVfr & FORMSET_CLASS_FRONT_PAGE) == 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
+ // 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
- // for (Line = 0; Line < BANNER_HEIGHT; Line++) {\r
+ // Goto another Hii Package list\r
//\r
- for (Line = (UINT8) LocalScreen.TopRow; Line < BANNER_HEIGHT + (UINT8) LocalScreen.TopRow; Line++) {\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
- // for (Alignment = 0; Alignment < BANNER_COLUMNS; Alignment++) {\r
+ // Not found the EFI_DEVICE_PATH_FROM_TEXT_PROTOCOL protocol.\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
- switch (Alignment - LocalScreen.LeftColumn) {\r
- case 0:\r
- //\r
- // Handle left column\r
- //\r
- PrintStringAt (LocalScreen.LeftColumn + BANNER_LEFT_COLUMN_INDENT, Line, StrFrontPageBanner);\r
- break;\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
+ gBrowserStatus = BROWSER_PROTOCOL_NOT_FOUND;\r
+ FreePool (StringPtr);\r
+ return Status;\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
+ 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
- FreePool (StrFrontPageBanner);\r
}\r
}\r
- }\r
\r
- ClearLines (\r
- LocalScreen.LeftColumn,\r
- LocalScreen.RightColumn,\r
- LocalScreen.BottomRow - STATUS_BAR_HEIGHT - gFooterHeight,\r
- LocalScreen.BottomRow - STATUS_BAR_HEIGHT - 1,\r
- KEYHELP_TEXT | KEYHELP_BACKGROUND\r
- );\r
-\r
- if ((gClassOfVfr & FORMSET_CLASS_FRONT_PAGE) != 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
+ 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
- Character = BOXDRAW_UP_RIGHT;\r
- PrintCharAt (LocalScreen.LeftColumn, LocalScreen.TopRow + NONE_FRONT_PAGE_HEADER_HEIGHT - 1, Character);\r
- PrintString (Buffer);\r
-\r
- Character = BOXDRAW_UP_LEFT;\r
- PrintChar (Character);\r
-\r
- if ((gClassOfVfr & FORMSET_CLASS_PLATFORM_SETUP) == FORMSET_CLASS_PLATFORM_SETUP) {\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
- // Print Bottom border line\r
- // +------------------------------------------------------------------------------+\r
- // ? ?\r
- // +------------------------------------------------------------------------------+\r
+ // Goto another Formset, check for uncommitted data\r
//\r
- Character = BOXDRAW_DOWN_RIGHT;\r
- PrintCharAt (LocalScreen.LeftColumn, LocalScreen.BottomRow - STATUS_BAR_HEIGHT - gFooterHeight, 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 - gFooterHeight + 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
+ if ((gBrowserSettingScope == FormLevel || gBrowserSettingScope == FormSetLevel) &&\r
+ IsNvUpdateRequiredForFormSet(Selection->FormSet)) {\r
+ if (!ProcessChangedData(Selection, FormSetLevel)) {\r
+ return EFI_SUCCESS;\r
+ }\r
}\r
+ }\r
\r
- Character = BOXDRAW_UP_RIGHT;\r
- PrintCharAt (LocalScreen.LeftColumn, LocalScreen.BottomRow - STATUS_BAR_HEIGHT - 1, Character);\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
- PrintString (Buffer);\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
- Character = BOXDRAW_UP_LEFT;\r
- PrintChar (Character);\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
\r
- FreePool (Buffer);\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
- Evaluate all expressions in a Form.\r
+ Process Question Config.\r
\r
- @param FormSet FormSet this Form belongs to.\r
- @param Form The Form.\r
+ @param Selection The UI menu selection.\r
+ @param Question The Question to be peocessed.\r
\r
- @retval EFI_SUCCESS The expression evaluated successfuly\r
+ @retval EFI_SUCCESS Question Config process success.\r
+ @retval Other Question Config process fail.\r
\r
**/\r
EFI_STATUS\r
-EvaluateFormExpressions (\r
- IN FORM_BROWSER_FORMSET *FormSet,\r
- IN FORM_BROWSER_FORM *Form\r
+ProcessQuestionConfig (\r
+ IN UI_MENU_SELECTION *Selection,\r
+ IN FORM_BROWSER_STATEMENT *Question\r
)\r
{\r
- EFI_STATUS Status;\r
- LIST_ENTRY *Link;\r
- FORM_EXPRESSION *Expression;\r
+ EFI_STATUS Status;\r
+ CHAR16 *ConfigResp;\r
+ CHAR16 *Progress;\r
+ EFI_HII_CONFIG_ACCESS_PROTOCOL *ConfigAccess;\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
+ if (Question->QuestionConfig == 0) {\r
+ return EFI_SUCCESS;\r
+ }\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
+ // Get <ConfigResp>\r
+ //\r
+ ConfigResp = GetToken (Question->QuestionConfig, Selection->FormSet->HiiHandle);\r
+ if (ConfigResp == NULL) {\r
+ return EFI_NOT_FOUND;\r
+ }\r
\r
- Status = EvaluateExpression (FormSet, Form, Expression);\r
- if (EFI_ERROR (Status)) {\r
- return Status;\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 EFI_SUCCESS;\r
+ return Status;\r
}\r
\r
-/*\r
-+------------------------------------------------------------------------------+\r
-? Setup Page ?\r
-+------------------------------------------------------------------------------+\r
-\r
-\r
-\r
-\r
-\r
-\r
-\r
-\r
-\r
-\r
-\r
-\r
-\r
-\r
-\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
-\r
/**\r
\r
+ Process the user input data.\r
\r
- Display form and wait for user to select one menu option, then return it.\r
+ @param UserInput The user input data.\r
+ @param ChangeHighlight Whether need to change the highlight statement. \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
@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
- 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
- UINT16 GlyphWidth;\r
-\r
- Handle = Selection->Handle;\r
- MenuItemCount = 0;\r
- ArrayEntry = 0;\r
- OutputString = NULL;\r
-\r
- UiInitMenu ();\r
-\r
- CopyMem (&LocalScreen, &gScreenDimensions, sizeof (EFI_SCREEN_DESCRIPTOR));\r
-\r
- StringPtr = GetToken (Selection->Form->FormTitle, Handle);\r
+ EFI_STATUS Status;\r
+ FORM_BROWSER_STATEMENT *Statement;\r
\r
- if ((gClassOfVfr & FORMSET_CLASS_FRONT_PAGE) != FORMSET_CLASS_FRONT_PAGE) {\r
- if (Selection->Form->ModalForm) {\r
- gST->ConOut->SetAttribute (gST->ConOut, TITLE_TEXT | EFI_BACKGROUND_BLACK);\r
- } else {\r
- gST->ConOut->SetAttribute (gST->ConOut, TITLE_TEXT | TITLE_BACKGROUND);\r
- }\r
- PrintStringAt (\r
- (LocalScreen.RightColumn + LocalScreen.LeftColumn - GetStringWidth (StringPtr) / 2) / 2,\r
- LocalScreen.TopRow + 1,\r
- StringPtr\r
- );\r
- }\r
+ Status = EFI_SUCCESS;\r
\r
//\r
- // Remove Buffer allocated for StringPtr after it has been used.\r
+ // When Exit from FormDisplay function, one of the below two cases must be true.\r
//\r
- FreePool (StringPtr);\r
+ ASSERT (UserInput->Action != 0 || UserInput->SelectedStatement != NULL);\r
\r
//\r
- // Evaluate all the Expressions in this Form\r
+ // Remove the last highligh question id, this id will update when show next form.\r
//\r
- Status = EvaluateFormExpressions (Selection->FormSet, Selection->Form);\r
- if (EFI_ERROR (Status)) {\r
- return Status;\r
- }\r
+ gCurrentSelection->QuestionId = 0;\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
+ //\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
- if (EvaluateExpressionList(Statement->Expression, FALSE, NULL, NULL) <= ExpressGrayOut) {\r
- StringPtr = GetToken (Statement->Prompt, Handle);\r
- ASSERT (StringPtr != NULL);\r
+ //\r
+ // Clear the highlight info.\r
+ //\r
+ gCurrentSelection->Statement = NULL;\r
\r
- Width = GetWidth (Statement, Handle);\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
- NumberOfLines = 1;\r
- ArrayEntry = 0;\r
- GlyphWidth = 1;\r
- for (; GetLineByWidth (StringPtr, Width, &GlyphWidth,&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
+ gCurrentSelection->Statement = Statement;\r
\r
- FreePool (OutputString);\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
- // 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
+ // Reset Question to default value specified by DefaultId\r
//\r
- MenuOption = UiAddMenuOption (StringPtr, Selection->Handle, Selection->Form, Statement, NumberOfLines, MenuItemCount);\r
- MenuItemCount++;\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
- if (MenuOption->IsQuestion && !MenuOption->ReadOnly) {\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
- // At least one item is not readonly, this Form is considered as editable\r
+ // Two password match, send it to Configuration Driver\r
//\r
- Selection->FormEditable = TRUE;\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
- Link = GetNextNode (&Selection->Form->StatementListHead, Link);\r
}\r
\r
- Status = UiDisplayMenu (Selection);\r
-\r
- UiFreeMenu ();\r
-\r
return Status;\r
}\r
\r
/**\r
- Initialize the HII String Token to the correct values.\r
-\r
-**/\r
-VOID\r
-InitializeBrowserStrings (\r
- VOID\r
- )\r
-{\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
- 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
- gProtocolNotFound = GetToken (STRING_TOKEN (PROTOCOL_NOT_FOUND), gHiiHandle);\r
- return ;\r
-}\r
-\r
-/**\r
- Free up the resource allocated for all strings required\r
- by Setup Browser.\r
\r
-**/\r
-VOID\r
-FreeBrowserStrings (\r
- VOID\r
- )\r
-{\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
- FreePool (gProtocolNotFound);\r
- return ;\r
-}\r
+ Display form and wait for user to select one menu option, then return it.\r
\r
-/**\r
- Show all registered HotKey help strings on bottom Rows.\r
+ @retval EFI_SUCESSS This function always return successfully for now.\r
\r
**/\r
-VOID\r
-PrintHotKeyHelpString (\r
+EFI_STATUS\r
+DisplayForm (\r
VOID\r
)\r
{\r
- UINTN CurrentCol;\r
- UINTN CurrentRow;\r
- UINTN BottomRowOfHotKeyHelp;\r
- UINTN ColumnWidth;\r
- UINTN Index;\r
- EFI_SCREEN_DESCRIPTOR LocalScreen;\r
- LIST_ENTRY *Link;\r
- BROWSER_HOT_KEY *HotKey;\r
+ EFI_STATUS Status;\r
+ USER_INPUT UserInput;\r
+ FORM_ENTRY_INFO *CurrentMenu;\r
+ BOOLEAN ChangeHighlight;\r
\r
- CopyMem (&LocalScreen, &gScreenDimensions, sizeof (EFI_SCREEN_DESCRIPTOR));\r
- ColumnWidth = (LocalScreen.RightColumn - LocalScreen.LeftColumn) / 3;\r
- BottomRowOfHotKeyHelp = LocalScreen.BottomRow - STATUS_BAR_HEIGHT - 3;\r
+ ZeroMem (&UserInput, sizeof (USER_INPUT));\r
\r
//\r
- // Calculate total number of Register HotKeys. \r
+ // Update the menu history data.\r
//\r
- Index = 0;\r
- Link = GetFirstNode (&gBrowserHotKeyList);\r
- while (!IsNull (&gBrowserHotKeyList, Link)) {\r
- HotKey = BROWSER_HOT_KEY_FROM_LINK (Link);\r
- //\r
- // Help string can't exceed ColumnWidth. One Row will show three Help information. \r
+ CurrentMenu = UiFindMenuList (gCurrentSelection->Handle, &gCurrentSelection->FormSetGuid, gCurrentSelection->FormId);\r
+ if (CurrentMenu == NULL) {\r
//\r
- if (StrLen (HotKey->HelpString) > ColumnWidth) {\r
- HotKey->HelpString[ColumnWidth] = L'\0';\r
- }\r
- //\r
- // Calculate help information Column and Row.\r
- //\r
- if ((Index % 3) != 2) {\r
- CurrentCol = LocalScreen.LeftColumn + (2 - Index % 3) * ColumnWidth;\r
- } else {\r
- CurrentCol = LocalScreen.LeftColumn + 2;\r
- }\r
- CurrentRow = BottomRowOfHotKeyHelp - Index / 3;\r
- //\r
- // Print HotKey help string on bottom Row.\r
+ // Current menu not found, add it to the menu tree\r
//\r
- PrintStringAt (CurrentCol, CurrentRow, HotKey->HelpString);\r
+ CurrentMenu = UiAddMenuList (gCurrentSelection->Handle, &gCurrentSelection->FormSetGuid,\r
+ gCurrentSelection->FormId, gCurrentSelection->QuestionId);\r
+ ASSERT (CurrentMenu != NULL);\r
+ }\r
+ gCurrentSelection->CurrentMenu = CurrentMenu;\r
\r
+ //\r
+ // Find currrent highlight statement.\r
+ //\r
+ if (gCurrentSelection->QuestionId == 0) {\r
//\r
- // Get Next Hot Key.\r
+ // Highlight not specified, fetch it from cached menu\r
//\r
- Link = GetNextNode (&gBrowserHotKeyList, Link);\r
- Index ++;\r
+ gCurrentSelection->QuestionId = CurrentMenu->QuestionId;\r
}\r
- \r
- return;\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
-**/\r
-VOID\r
-UpdateKeyHelp (\r
- IN UI_MENU_SELECTION *Selection,\r
- IN UI_MENU_OPTION *MenuOption,\r
- IN BOOLEAN Selected\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
- gST->ConOut->SetAttribute (gST->ConOut, KEYHELP_TEXT | KEYHELP_BACKGROUND);\r
\r
- if (Selection->Form->ModalForm) {\r
- return;\r
+ //\r
+ // Evaluate all the Expressions in this Form\r
+ //\r
+ Status = EvaluateFormExpressions (gCurrentSelection->FormSet, gCurrentSelection->Form);\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
}\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) / 3 * 2;\r
-\r
- StartColumnOfHelp = LocalScreen.LeftColumn + 2;\r
- LeftColumnOfHelp = LocalScreen.LeftColumn + 1;\r
- RightColumnOfHelp = LocalScreen.RightColumn - 2;\r
- TopRowOfHelp = LocalScreen.BottomRow - STATUS_BAR_HEIGHT - gFooterHeight + 1;\r
- BottomRowOfHelp = LocalScreen.BottomRow - STATUS_BAR_HEIGHT - 2;\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
- //\r
- // On system setting, HotKey will show on every form.\r
- //\r
- if (gBrowserSettingScope == SystemLevel ||\r
- (Selection->FormEditable && gFunctionKeySetting != NONE_FUNCTION_KEY_SETTING)) {\r
- PrintHotKeyHelpString ();\r
- }\r
-\r
- if ((gClassOfVfr & FORMSET_CLASS_PLATFORM_SETUP) == FORMSET_CLASS_PLATFORM_SETUP) {\r
- PrintStringAt (ThdCol, BottomRowOfHelp, gEscapeString);\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, gEnterString);\r
- PrintStringAt (StartColumnOfHelp, TopRowOfHelp, 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 (StartColumnOfHelp, TopRowOfHelp, gAdjustNumber);\r
- } \r
- PrintStringAt (SecCol, BottomRowOfHelp, gEnterString);\r
- }\r
- } else {\r
- PrintStringAt (SecCol, BottomRowOfHelp, gEnterCommitString);\r
-\r
- //\r
- // If it is a selected numeric with manual input, display different message\r
- //\r
- if ((Statement->Operand == EFI_IFR_NUMERIC_OP) || \r
- (Statement->Operand == EFI_IFR_DATE_OP) ||\r
- (Statement->Operand == EFI_IFR_TIME_OP)) {\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
-\r
- if (Statement->Operand == EFI_IFR_ORDERED_LIST_OP) {\r
- PrintStringAt (StartColumnOfHelp, TopRowOfHelp, gPlusString);\r
- PrintStringAt (ThdCol, TopRowOfHelp, gMinusString);\r
- }\r
-\r
- PrintStringAt (ThdCol, BottomRowOfHelp, gEnterEscapeString);\r
- }\r
- break;\r
-\r
- case EFI_IFR_CHECKBOX_OP:\r
- ClearLines (LeftColumnOfHelp, RightColumnOfHelp, TopRowOfHelp, BottomRowOfHelp, KEYHELP_TEXT | KEYHELP_BACKGROUND);\r
-\r
- //\r
- // On system setting, HotKey will show on every form.\r
- //\r
- if (gBrowserSettingScope == SystemLevel ||\r
- (Selection->FormEditable && gFunctionKeySetting != NONE_FUNCTION_KEY_SETTING)) {\r
- PrintHotKeyHelpString ();\r
- }\r
- if ((gClassOfVfr & FORMSET_CLASS_PLATFORM_SETUP) == FORMSET_CLASS_PLATFORM_SETUP) {\r
- PrintStringAt (ThdCol, BottomRowOfHelp, gEscapeString);\r
- }\r
+ UpdateDisplayFormData ();\r
\r
- PrintAt (StartColumnOfHelp, BottomRowOfHelp, L"%c%c%s", ARROW_UP, ARROW_DOWN, gMoveHighlight);\r
- PrintStringAt (SecCol, BottomRowOfHelp, gToggleCheckBox);\r
- break;\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
- 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
- case EFI_IFR_SUBTITLE_OP:\r
- ClearLines (LeftColumnOfHelp, RightColumnOfHelp, TopRowOfHelp, BottomRowOfHelp, KEYHELP_TEXT | KEYHELP_BACKGROUND);\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 (!Selected) {\r
- //\r
- // On system setting, HotKey will show on every form.\r
- //\r
- if (gBrowserSettingScope == SystemLevel ||\r
- (Selection->FormEditable && gFunctionKeySetting != NONE_FUNCTION_KEY_SETTING)) {\r
- PrintHotKeyHelpString ();\r
- }\r
- if ((gClassOfVfr & FORMSET_CLASS_PLATFORM_SETUP) == FORMSET_CLASS_PLATFORM_SETUP) {\r
- PrintStringAt (ThdCol, BottomRowOfHelp, gEscapeString);\r
- }\r
+ Status = ProcessUserInput (&UserInput, ChangeHighlight);\r
\r
- PrintAt (StartColumnOfHelp, BottomRowOfHelp, L"%c%c%s", ARROW_UP, ARROW_DOWN, gMoveHighlight);\r
- if (Statement->Operand != EFI_IFR_TEXT_OP && Statement->Operand != EFI_IFR_SUBTITLE_OP) {\r
- PrintStringAt (SecCol, BottomRowOfHelp, gEnterString);\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
- }\r
- break;\r
+ FreeDisplayFormData();\r
\r
- default:\r
- break;\r
- }\r
+ return Status;\r
}\r
\r
/**\r
}\r
\r
/**\r
- check whether the formset need to update the NV.\r
+ Update the NV flag info for this form set.\r
\r
@param FormSet FormSet data structure.\r
\r
- @retval TRUE Need to update the NV.\r
- @retval FALSE No need to update the NV.\r
**/\r
-BOOLEAN \r
-IsNvUpdateRequired (\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
+ RetVal = FALSE;\r
\r
Link = GetFirstNode (&FormSet->FormListHead);\r
while (!IsNull (&FormSet->FormListHead, Link)) {\r
Form = FORM_BROWSER_FORM_FROM_LINK (Link);\r
\r
- if (Form->NvUpdateRequired ) {\r
- return TRUE;\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
+ Update the NvUpdateRequired flag for a form.\r
+\r
+ @param Form Form data structure.\r
+\r
+**/\r
+BOOLEAN\r
+IsNvUpdateRequiredForForm (\r
+ IN FORM_BROWSER_FORM *Form\r
+ )\r
+{\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
- check whether the formset need to update the NV.\r
+ Check whether the storage data for current form set is changed.\r
\r
- @param FormSet FormSet data structure.\r
- @param SetValue Whether set new value or clear old value.\r
+ @param FormSet FormSet data structure.\r
\r
+ @retval TRUE Data is changed.\r
+ @retval FALSE Data is not changed.\r
**/\r
-VOID\r
-UpdateNvInfoInForm (\r
- IN FORM_BROWSER_FORMSET *FormSet,\r
- IN BOOLEAN SetValue\r
+BOOLEAN \r
+IsStorageDataChangedForFormSet (\r
+ IN FORM_BROWSER_FORMSET *FormSet\r
)\r
{\r
LIST_ENTRY *Link;\r
- FORM_BROWSER_FORM *Form;\r
- \r
- Link = GetFirstNode (&FormSet->FormListHead);\r
- while (!IsNull (&FormSet->FormListHead, Link)) {\r
- Form = FORM_BROWSER_FORM_FROM_LINK (Link);\r
+ FORMSET_STORAGE *Storage;\r
+ BROWSER_STORAGE *BrowserStorage;\r
+ CHAR16 *ConfigRespNew;\r
+ CHAR16 *ConfigRespOld;\r
+ BOOLEAN RetVal;\r
\r
- Form->NvUpdateRequired = SetValue;\r
+ RetVal = FALSE;\r
+ ConfigRespNew = NULL;\r
+ ConfigRespOld = NULL;\r
\r
- Link = GetNextNode (&FormSet->FormListHead, Link);\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
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 Repaint Whether need to repaint the menu.\r
- @param NewLine Whether need to show at new line.\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 Need return.\r
- @retval FALSE No need to return.\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 BOOLEAN *Repaint, \r
- IN BOOLEAN *NewLine \r
+ IN OUT UI_MENU_SELECTION *Selection,\r
+ IN BROWSER_SETTING_SCOPE SettingLevel\r
)\r
{\r
- UI_MENU_LIST *CurrentMenu;\r
- CHAR16 YesResponse;\r
- CHAR16 NoResponse;\r
- EFI_INPUT_KEY Key;\r
- BROWSER_SETTING_SCOPE Scope;\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 && CurrentMenu->Parent != NULL) {\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, &CurrentMenu->Parent->FormSetGuid)) {\r
- //\r
- // The parent menu and current menu are in the same formset\r
- //\r
- Selection->Action = UI_ACTION_REFRESH_FORM;\r
- Scope = FormLevel;\r
- } else {\r
- Selection->Action = UI_ACTION_REFRESH_FORMSET;\r
- CopyMem (&Selection->FormSetGuid, &CurrentMenu->Parent->FormSetGuid, sizeof (EFI_GUID));\r
- Selection->Handle = CurrentMenu->Parent->HiiHandle;\r
- Scope = FormSetLevel;\r
- }\r
-\r
- //\r
- // Form Level Check whether the data is changed.\r
- //\r
- if ((gBrowserSettingScope == FormLevel && Selection->Form->NvUpdateRequired) ||\r
- (gBrowserSettingScope == FormSetLevel && IsNvUpdateRequired(Selection->FormSet) && Scope == FormSetLevel)) {\r
- gST->ConIn->ReadKeyStroke (gST->ConIn, &Key);\r
- \r
- YesResponse = gYesResponse[0];\r
- NoResponse = gNoResponse[0];\r
- \r
- //\r
- // If NV flag is up, prompt user\r
- //\r
- do {\r
- CreateDialog (4, TRUE, 0, NULL, &Key, gEmptyString, gSaveChanges, gAreYouSure, gEmptyString);\r
- } while\r
- (\r
- (Key.ScanCode != SCAN_ESC) &&\r
- ((Key.UnicodeChar | UPPER_LOWER_CASE_OFFSET) != (NoResponse | UPPER_LOWER_CASE_OFFSET)) &&\r
- ((Key.UnicodeChar | UPPER_LOWER_CASE_OFFSET) != (YesResponse | UPPER_LOWER_CASE_OFFSET))\r
- );\r
- \r
- if (Key.ScanCode == SCAN_ESC) {\r
+ if (CompareGuid (&CurrentMenu->FormSetGuid, &ParentMenu->FormSetGuid)) {\r
+ if (SettingLevel == FormSetLevel) {\r
//\r
- // User hits the ESC key, Ingore. \r
+ // Find a menu which has different formset guid with current.\r
//\r
- if (Repaint != NULL) {\r
- *Repaint = TRUE;\r
- }\r
- if (NewLine != NULL) {\r
- *NewLine = TRUE;\r
+ while (CompareGuid (&CurrentMenu->FormSetGuid, &ParentMenu->FormSetGuid)) {\r
+ CurrentMenu = ParentMenu;\r
+ if ((ParentMenu = UiFindParentMenu(CurrentMenu)) == NULL) {\r
+ break;\r
+ }\r
}\r
\r
- Selection->Action = UI_ACTION_NONE;\r
- return FALSE;\r
- }\r
- \r
- if ((Key.UnicodeChar | UPPER_LOWER_CASE_OFFSET) == (YesResponse | UPPER_LOWER_CASE_OFFSET)) {\r
- //\r
- // If the user hits the YesResponse key\r
- //\r
- SubmitForm (Selection->FormSet, Selection->Form, Scope);\r
+ if (ParentMenu != NULL) {\r
+ Scope = FormSetLevel;\r
+ }\r
} else {\r
- //\r
- // If the user hits the NoResponse key\r
- //\r
- DiscardForm (Selection->FormSet, Selection->Form, Scope);\r
+ Scope = FormLevel;\r
}\r
+ } else {\r
+ Scope = FormSetLevel;\r
}\r
-\r
- Selection->Statement = NULL;\r
-\r
- Selection->FormId = CurrentMenu->Parent->FormId;\r
- Selection->QuestionId = CurrentMenu->Parent->QuestionId;\r
-\r
- //\r
- // Clear highlight record for this menu\r
- //\r
- CurrentMenu->QuestionId = 0;\r
- return FALSE;\r
- }\r
-\r
- if ((gClassOfVfr & FORMSET_CLASS_FRONT_PAGE) == FORMSET_CLASS_FRONT_PAGE) {\r
- //\r
- // We never exit FrontPage, so skip the ESC\r
- //\r
- Selection->Action = UI_ACTION_NONE;\r
- return FALSE;\r
}\r
\r
//\r
- // We are going to leave current FormSet, so check uncommited data in this FormSet\r
+ // Form Level Check whether the data is changed.\r
//\r
- if (gBrowserSettingScope != SystemLevel && IsNvUpdateRequired(Selection->FormSet)) {\r
- gST->ConIn->ReadKeyStroke (gST->ConIn, &Key);\r
-\r
- YesResponse = gYesResponse[0];\r
- NoResponse = gNoResponse[0];\r
-\r
- //\r
- // If NV flag is up, prompt user\r
- //\r
- do {\r
- CreateDialog (4, TRUE, 0, NULL, &Key, gEmptyString, gSaveChanges, gAreYouSure, gEmptyString);\r
- } while\r
- (\r
- (Key.ScanCode != SCAN_ESC) &&\r
- ((Key.UnicodeChar | UPPER_LOWER_CASE_OFFSET) != (NoResponse | UPPER_LOWER_CASE_OFFSET)) &&\r
- ((Key.UnicodeChar | UPPER_LOWER_CASE_OFFSET) != (YesResponse | UPPER_LOWER_CASE_OFFSET))\r
- );\r
-\r
- if (Key.ScanCode == SCAN_ESC) {\r
- //\r
- // User hits the ESC key\r
- //\r
- if (Repaint != NULL) {\r
- *Repaint = TRUE;\r
- }\r
-\r
- if (NewLine != NULL) {\r
- *NewLine = TRUE;\r
- }\r
-\r
- Selection->Action = UI_ACTION_NONE;\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 ((Key.UnicodeChar | UPPER_LOWER_CASE_OFFSET) == (YesResponse | UPPER_LOWER_CASE_OFFSET)) {\r
- //\r
- // If the user hits the YesResponse key\r
- //\r
- SubmitForm (Selection->FormSet, Selection->Form, FormSetLevel);\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
- //\r
- // If the user hits the NoResponse key\r
- //\r
- DiscardForm (Selection->FormSet, Selection->Form, FormSetLevel);\r
+ Selection->Action = UI_ACTION_REFRESH_FORMSET;\r
+ CopyMem (&Selection->FormSetGuid, &ParentMenu->FormSetGuid, sizeof (EFI_GUID));\r
+ Selection->Handle = ParentMenu->HiiHandle;\r
}\r
- }\r
\r
- Selection->Statement = NULL;\r
- if (CurrentMenu != NULL) {\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
case EFI_BROWSER_ACTION_REQUEST_RESET:\r
DiscardFormIsRequired = TRUE;\r
gResetRequired = TRUE;\r
- Selection->Action = UI_ACTION_EXIT;\r
+ NeedExit = TRUE;\r
break;\r
\r
case EFI_BROWSER_ACTION_REQUEST_SUBMIT:\r
SubmitFormIsRequired = TRUE;\r
- Selection->Action = UI_ACTION_EXIT;\r
+ NeedExit = TRUE;\r
break;\r
\r
case EFI_BROWSER_ACTION_REQUEST_EXIT:\r
DiscardFormIsRequired = TRUE;\r
- Selection->Action = UI_ACTION_EXIT;\r
+ NeedExit = TRUE;\r
break;\r
\r
case EFI_BROWSER_ACTION_REQUEST_FORM_SUBMIT_EXIT:\r
\r
case EFI_BROWSER_ACTION_REQUEST_FORM_DISCARD_EXIT:\r
DiscardFormIsRequired = TRUE;\r
- SettingLevel = FormLevel; \r
+ SettingLevel = FormLevel;\r
NeedExit = TRUE;\r
break;\r
\r
}\r
\r
if (NeedExit) {\r
- FindNextMenu (Selection, NULL, NULL);\r
+ FindNextMenu (Selection, SettingLevel);\r
}\r
\r
return Status;\r
EFI_HANDLE NotifyHandle;\r
FORM_BROWSER_STATEMENT *Statement;\r
EFI_HII_CONFIG_ACCESS_PROTOCOL *ConfigAccess;\r
- EFI_INPUT_KEY Key;\r
\r
- gMenuRefreshHead = NULL;\r
ConfigAccess = Selection->FormSet->ConfigAccess;\r
\r
//\r
//\r
// Initialize current settings of Questions in this FormSet\r
//\r
- Status = InitializeCurrentSetting (Selection->FormSet);\r
- if (EFI_ERROR (Status)) {\r
- goto Done;\r
- }\r
+ InitializeCurrentSetting (Selection->FormSet);\r
\r
//\r
- // Update gOldFormSet on maintain back up FormSet list.\r
- // And, make gOldFormSet point to current FormSet. \r
+ // Initilize Action field.\r
//\r
- if (gOldFormSet != NULL) {\r
- RemoveEntryList (&gOldFormSet->Link);\r
- DestroyFormSet (gOldFormSet);\r
- }\r
- gOldFormSet = Selection->FormSet;\r
- InsertTailList (&gBrowserFormSetList, &gOldFormSet->Link);\r
+ Selection->Action = UI_ACTION_REFRESH_FORM;\r
+\r
+ //\r
+ // Clean the mCurFakeQestId value is formset refreshed.\r
+ //\r
+ mCurFakeQestId = 0;\r
\r
do {\r
//\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
-\r
+ gBrowserStatus = BROWSER_FORM_SUPPRESS;\r
Status = EFI_NOT_FOUND;\r
goto Done;\r
}\r
((Selection->Handle != mCurrentHiiHandle) ||\r
(!CompareGuid (&Selection->FormSetGuid, &mCurrentFormSetGuid)) ||\r
(Selection->FormId != mCurrentFormId))) {\r
-\r
//\r
// Keep current form information\r
//\r
goto Done;\r
}\r
\r
- //\r
- // EXIT requests to close form.\r
- //\r
- if (Selection->Action == UI_ACTION_EXIT) {\r
- goto Done;\r
- }\r
//\r
// IFR is updated during callback of open form, force to reparse the IFR binary\r
//\r
goto Done;\r
}\r
\r
- //\r
- // EXIT requests to close form.\r
- //\r
- if (Selection->Action == UI_ACTION_EXIT) {\r
- goto Done;\r
- }\r
//\r
// IFR is updated during callback of read value, force to reparse the IFR binary\r
//\r
break;\r
}\r
\r
- //\r
- // Displays the Header and Footer borders\r
- //\r
- DisplayPageFrame (Selection);\r
-\r
//\r
// Display form\r
//\r
- Status = DisplayForm (Selection);\r
+ Status = DisplayForm ();\r
if (EFI_ERROR (Status)) {\r
goto Done;\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
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 && Selection->Action != UI_ACTION_EXIT) {\r
+ Status = ProcessCallBackFunction(Selection, Statement, EFI_BROWSER_ACTION_CHANGING, FALSE);\r
+ if (Statement->Operand == EFI_IFR_REF_OP) {\r
//\r
// Process dynamic update ref opcode.\r
//\r
if (!EFI_ERROR (Status)) {\r
- Status = ProcessGotoOpCode(Statement, Selection, NULL, NULL);\r
+ Status = ProcessGotoOpCode(Statement, Selection);\r
}\r
\r
//\r
}\r
}\r
\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 FormSetLevel:\r
+ case FormLevel:\r
+ FindNextMenu (Selection, gBrowserSettingScope);\r
+ break;\r
+\r
+ default:\r
+ break;\r
+ }\r
+\r
+ gExitRequired = FALSE;\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
+++ /dev/null
-/** @file\r
-Basic Ascii AvSPrintf() function named VSPrint(). VSPrint() enables very\r
-simple implemenation of SPrint() and Print() to support debug.\r
-\r
-You can not Print more than EFI_DRIVER_LIB_MAX_PRINT_BUFFER characters at a\r
-time. This makes the implementation very simple.\r
-\r
-VSPrint, Print, SPrint format specification has the follwoing form\r
-\r
-%type\r
-\r
-type:\r
- 'S','s' - argument is an Unicode string\r
- 'c' - argument is an ascii character\r
- '%' - Print a %\r
-\r
-\r
-Copyright (c) 2004 - 2012, 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
-THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
-WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
-\r
-**/\r
-\r
-#include "Setup.h"\r
-\r
-/**\r
- The internal function prints to the EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL\r
- protocol instance.\r
-\r
- @param Column The position of the output string.\r
- @param Row The position of the output string.\r
- @param Out The EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL instance.\r
- @param Fmt The format string.\r
- @param Args The additional argument for the variables in the format string.\r
-\r
- @return Number of Unicode character printed.\r
-\r
-**/\r
-UINTN\r
-PrintInternal (\r
- IN UINTN Column,\r
- IN UINTN Row,\r
- IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *Out,\r
- IN CHAR16 *Fmt,\r
- IN VA_LIST Args\r
- )\r
-{\r
- CHAR16 *Buffer;\r
- CHAR16 *BackupBuffer;\r
- UINTN Index;\r
- UINTN PreviousIndex;\r
- UINTN Count;\r
-\r
- //\r
- // For now, allocate an arbitrarily long buffer\r
- //\r
- Buffer = AllocateZeroPool (0x10000);\r
- BackupBuffer = AllocateZeroPool (0x10000);\r
- ASSERT (Buffer);\r
- ASSERT (BackupBuffer);\r
-\r
- if (Column != (UINTN) -1) {\r
- Out->SetCursorPosition (Out, Column, Row);\r
- }\r
-\r
- UnicodeVSPrint (Buffer, 0x10000, Fmt, Args);\r
-\r
- Out->Mode->Attribute = Out->Mode->Attribute & 0x7f;\r
-\r
- Out->SetAttribute (Out, Out->Mode->Attribute);\r
-\r
- Index = 0;\r
- PreviousIndex = 0;\r
- Count = 0;\r
-\r
- do {\r
- for (; (Buffer[Index] != NARROW_CHAR) && (Buffer[Index] != WIDE_CHAR) && (Buffer[Index] != 0); Index++) {\r
- BackupBuffer[Index] = Buffer[Index];\r
- }\r
-\r
- if (Buffer[Index] == 0) {\r
- break;\r
- }\r
- //\r
- // Null-terminate the temporary string\r
- //\r
- BackupBuffer[Index] = 0;\r
-\r
- //\r
- // Print this out, we are about to switch widths\r
- //\r
- Out->OutputString (Out, &BackupBuffer[PreviousIndex]);\r
- Count += StrLen (&BackupBuffer[PreviousIndex]);\r
-\r
- //\r
- // Preserve the current index + 1, since this is where we will start printing from next\r
- //\r
- PreviousIndex = Index + 1;\r
-\r
- //\r
- // We are at a narrow or wide character directive. Set attributes and strip it and print it\r
- //\r
- if (Buffer[Index] == NARROW_CHAR) {\r
- //\r
- // Preserve bits 0 - 6 and zero out the rest\r
- //\r
- Out->Mode->Attribute = Out->Mode->Attribute & 0x7f;\r
- Out->SetAttribute (Out, Out->Mode->Attribute);\r
- } else {\r
- //\r
- // Must be wide, set bit 7 ON\r
- //\r
- Out->Mode->Attribute = Out->Mode->Attribute | EFI_WIDE_ATTRIBUTE;\r
- Out->SetAttribute (Out, Out->Mode->Attribute);\r
- }\r
-\r
- Index++;\r
-\r
- } while (Buffer[Index] != 0);\r
-\r
- //\r
- // We hit the end of the string - print it\r
- //\r
- Out->OutputString (Out, &BackupBuffer[PreviousIndex]);\r
- Count += StrLen (&BackupBuffer[PreviousIndex]);\r
-\r
- FreePool (Buffer);\r
- FreePool (BackupBuffer);\r
- return Count;\r
-}\r
-\r
-\r
-/**\r
- Prints a formatted unicode string to the default console.\r
-\r
- @param Fmt Format string\r
- @param ... Variable argument list for format string.\r
-\r
- @return Length of string printed to the console.\r
-\r
-**/\r
-UINTN\r
-EFIAPI\r
-ConsolePrint (\r
- IN CHAR16 *Fmt,\r
- ...\r
- )\r
-{\r
- VA_LIST Args;\r
- UINTN LengthOfPrinted;\r
-\r
- VA_START (Args, Fmt);\r
- LengthOfPrinted = PrintInternal ((UINTN) -1, (UINTN) -1, gST->ConOut, Fmt, Args);\r
- VA_END (Args);\r
- return LengthOfPrinted;\r
-}\r
-\r
-\r
-/**\r
- Prints a unicode string to the default console,\r
- using L"%s" format.\r
-\r
- @param String String pointer.\r
-\r
- @return Length of string printed to the console\r
-\r
-**/\r
-UINTN\r
-PrintString (\r
- IN CHAR16 *String\r
- )\r
-{\r
- return ConsolePrint (L"%s", String);\r
-}\r
-\r
-\r
-/**\r
- Prints a chracter to the default console,\r
- using L"%c" format.\r
-\r
- @param Character Character to print.\r
-\r
- @return Length of string printed to the console.\r
-\r
-**/\r
-UINTN\r
-PrintChar (\r
- CHAR16 Character\r
- )\r
-{\r
- return ConsolePrint (L"%c", Character);\r
-}\r
-\r
-\r
-/**\r
- Prints a formatted unicode string to the default console, at\r
- the supplied cursor position.\r
-\r
- @param Column The cursor position to print the string at.\r
- @param Row The cursor position to print the string at.\r
- @param Fmt Format string.\r
- @param ... Variable argument list for format string.\r
-\r
- @return Length of string printed to the console\r
-\r
-**/\r
-UINTN\r
-EFIAPI\r
-PrintAt (\r
- IN UINTN Column,\r
- IN UINTN Row,\r
- IN CHAR16 *Fmt,\r
- ...\r
- )\r
-{\r
- VA_LIST Args;\r
- UINTN LengthOfPrinted;\r
-\r
- VA_START (Args, Fmt);\r
- LengthOfPrinted = PrintInternal (Column, Row, gST->ConOut, Fmt, Args);\r
- VA_END (Args);\r
- return LengthOfPrinted;\r
-}\r
-\r
-\r
-/**\r
- Prints a unicode string to the default console, at\r
- the supplied cursor position, using L"%s" format.\r
-\r
- @param Column The cursor position to print the string at.\r
- @param Row The cursor position to print the string at\r
- @param String String pointer.\r
-\r
- @return Length of string printed to the console\r
-\r
-**/\r
-UINTN\r
-PrintStringAt (\r
- IN UINTN Column,\r
- IN UINTN Row,\r
- IN CHAR16 *String\r
- )\r
-{\r
- return PrintAt (Column, Row, L"%s", String);\r
-}\r
-\r
-\r
-/**\r
- Prints a chracter to the default console, at\r
- the supplied cursor position, using L"%c" format.\r
-\r
- @param Column The cursor position to print the string at.\r
- @param Row The cursor position to print the string at.\r
- @param Character Character to print.\r
-\r
- @return Length of string printed to the console.\r
-\r
-**/\r
-UINTN\r
-PrintCharAt (\r
- IN UINTN Column,\r
- IN UINTN Row,\r
- CHAR16 Character\r
- )\r
-{\r
- return PrintAt (Column, Row, L"%c", Character);\r
-}\r
+++ /dev/null
-/** @file\r
-Implementation for handling the User Interface option processing.\r
-\r
-\r
-Copyright (c) 2004 - 2012, 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
-THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
-WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
-\r
-**/\r
-\r
-#include "Setup.h"\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
- Search an Option of a Question by its value.\r
-\r
- @param Question The Question\r
- @param OptionValue Value for Option to be searched.\r
-\r
- @retval Pointer Pointer to the found Option.\r
- @retval NULL Option not found.\r
-\r
-**/\r
-QUESTION_OPTION *\r
-ValueToOption (\r
- IN FORM_BROWSER_STATEMENT *Question,\r
- IN EFI_HII_VALUE *OptionValue\r
- )\r
-{\r
- LIST_ENTRY *Link;\r
- QUESTION_OPTION *Option;\r
- INTN Result;\r
-\r
- Link = GetFirstNode (&Question->OptionListHead);\r
- while (!IsNull (&Question->OptionListHead, Link)) {\r
- Option = QUESTION_OPTION_FROM_LINK (Link);\r
-\r
- if ((CompareHiiValue (&Option->Value, OptionValue, &Result, NULL) == EFI_SUCCESS) && (Result == 0)) {\r
- //\r
- // Check the suppressif condition, only a valid option can be return.\r
- //\r
- if ((Option->SuppressExpression == NULL) ||\r
- ((EvaluateExpressionList(Option->SuppressExpression, FALSE, NULL, NULL) == ExpressFalse))) {\r
- return Option;\r
- }\r
- }\r
-\r
- Link = GetNextNode (&Question->OptionListHead, Link);\r
- }\r
-\r
- return NULL;\r
-}\r
-\r
-\r
-/**\r
- Return data element in an Array by its Index.\r
-\r
- @param Array The data array.\r
- @param Type Type of the data in this array.\r
- @param Index Zero based index for data in this array.\r
-\r
- @retval Value The data to be returned\r
-\r
-**/\r
-UINT64\r
-GetArrayData (\r
- IN VOID *Array,\r
- IN UINT8 Type,\r
- IN UINTN Index\r
- )\r
-{\r
- UINT64 Data;\r
-\r
- ASSERT (Array != NULL);\r
-\r
- Data = 0;\r
- switch (Type) {\r
- case EFI_IFR_TYPE_NUM_SIZE_8:\r
- Data = (UINT64) *(((UINT8 *) Array) + Index);\r
- break;\r
-\r
- case EFI_IFR_TYPE_NUM_SIZE_16:\r
- Data = (UINT64) *(((UINT16 *) Array) + Index);\r
- break;\r
-\r
- case EFI_IFR_TYPE_NUM_SIZE_32:\r
- Data = (UINT64) *(((UINT32 *) Array) + Index);\r
- break;\r
-\r
- case EFI_IFR_TYPE_NUM_SIZE_64:\r
- Data = (UINT64) *(((UINT64 *) Array) + Index);\r
- break;\r
-\r
- default:\r
- break;\r
- }\r
-\r
- return Data;\r
-}\r
-\r
-\r
-/**\r
- Set value of a data element in an Array by its Index.\r
-\r
- @param Array The data array.\r
- @param Type Type of the data in this array.\r
- @param Index Zero based index for data in this array.\r
- @param Value The value to be set.\r
-\r
-**/\r
-VOID\r
-SetArrayData (\r
- IN VOID *Array,\r
- IN UINT8 Type,\r
- IN UINTN Index,\r
- IN UINT64 Value\r
- )\r
-{\r
-\r
- ASSERT (Array != NULL);\r
-\r
- switch (Type) {\r
- case EFI_IFR_TYPE_NUM_SIZE_8:\r
- *(((UINT8 *) Array) + Index) = (UINT8) Value;\r
- break;\r
-\r
- case EFI_IFR_TYPE_NUM_SIZE_16:\r
- *(((UINT16 *) Array) + Index) = (UINT16) Value;\r
- break;\r
-\r
- case EFI_IFR_TYPE_NUM_SIZE_32:\r
- *(((UINT32 *) Array) + Index) = (UINT32) Value;\r
- break;\r
-\r
- case EFI_IFR_TYPE_NUM_SIZE_64:\r
- *(((UINT64 *) Array) + Index) = (UINT64) Value;\r
- break;\r
-\r
- default:\r
- break;\r
- }\r
-}\r
-\r
-/**\r
- Check whether this value already in the array, if yes, return the index.\r
-\r
- @param Array The data array.\r
- @param Type Type of the data in this array.\r
- @param Value The value to be find.\r
- @param Index The index in the array which has same value with Value.\r
- \r
- @retval TRUE Found the value in the array.\r
- @retval FALSE Not found the value.\r
-\r
-**/\r
-BOOLEAN \r
-FindArrayData (\r
- IN VOID *Array,\r
- IN UINT8 Type,\r
- IN UINT64 Value,\r
- OUT UINTN *Index OPTIONAL\r
- )\r
-{\r
- UINTN Count;\r
- UINT64 TmpValue;\r
- \r
- ASSERT (Array != NULL);\r
-\r
- Count = 0;\r
- TmpValue = 0;\r
-\r
- while ((TmpValue = GetArrayData (Array, Type, Count)) != 0) {\r
- if (Value == TmpValue) {\r
- if (Index != NULL) {\r
- *Index = Count;\r
- }\r
- return TRUE;\r
- }\r
-\r
- Count ++;\r
- }\r
-\r
- return FALSE;\r
-}\r
-\r
-/**\r
- Print Question Value according to it's storage width and display attributes.\r
-\r
- @param Question The Question to be printed.\r
- @param FormattedNumber Buffer for output string.\r
- @param BufferSize The FormattedNumber buffer size in bytes.\r
-\r
- @retval EFI_SUCCESS Print success.\r
- @retval EFI_BUFFER_TOO_SMALL Buffer size is not enough for formatted number.\r
-\r
-**/\r
-EFI_STATUS\r
-PrintFormattedNumber (\r
- IN FORM_BROWSER_STATEMENT *Question,\r
- IN OUT CHAR16 *FormattedNumber,\r
- IN UINTN BufferSize\r
- )\r
-{\r
- INT64 Value;\r
- CHAR16 *Format;\r
- EFI_HII_VALUE *QuestionValue;\r
-\r
- if (BufferSize < (21 * sizeof (CHAR16))) {\r
- return EFI_BUFFER_TOO_SMALL;\r
- }\r
-\r
- QuestionValue = &Question->HiiValue;\r
-\r
- Value = (INT64) QuestionValue->Value.u64;\r
- switch (Question->Flags & EFI_IFR_DISPLAY) {\r
- case EFI_IFR_DISPLAY_INT_DEC:\r
- switch (QuestionValue->Type) {\r
- case EFI_IFR_NUMERIC_SIZE_1:\r
- Value = (INT64) ((INT8) QuestionValue->Value.u8);\r
- break;\r
-\r
- case EFI_IFR_NUMERIC_SIZE_2:\r
- Value = (INT64) ((INT16) QuestionValue->Value.u16);\r
- break;\r
-\r
- case EFI_IFR_NUMERIC_SIZE_4:\r
- Value = (INT64) ((INT32) QuestionValue->Value.u32);\r
- break;\r
-\r
- case EFI_IFR_NUMERIC_SIZE_8:\r
- default:\r
- break;\r
- }\r
-\r
- if (Value < 0) {\r
- Value = -Value;\r
- Format = L"-%ld";\r
- } else {\r
- Format = L"%ld";\r
- }\r
- break;\r
-\r
- case EFI_IFR_DISPLAY_UINT_DEC:\r
- Format = L"%ld";\r
- break;\r
-\r
- case EFI_IFR_DISPLAY_UINT_HEX:\r
- Format = L"%lx";\r
- break;\r
-\r
- default:\r
- return EFI_UNSUPPORTED;\r
- break;\r
- }\r
-\r
- UnicodeSPrint (FormattedNumber, BufferSize, Format, Value);\r
-\r
- return EFI_SUCCESS;\r
-}\r
-\r
-\r
-/**\r
- Password may be stored as encrypted by Configuration Driver. When change a\r
- password, user will be challenged with old password. To validate user input old\r
- password, we will send the clear text to Configuration Driver via Callback().\r
- Configuration driver is responsible to check the passed in password and return\r
- the validation result. If validation pass, state machine in password Callback()\r
- will transit from BROWSER_STATE_VALIDATE_PASSWORD to BROWSER_STATE_SET_PASSWORD.\r
- After user type in new password twice, Callback() will be invoked to send the\r
- new password to Configuration Driver.\r
-\r
- @param Selection Pointer to UI_MENU_SELECTION.\r
- @param MenuOption The MenuOption for this password Question.\r
- @param String The clear text of password.\r
-\r
- @retval EFI_NOT_AVAILABLE_YET Callback() request to terminate password input.\r
- @return In state of BROWSER_STATE_VALIDATE_PASSWORD:\r
- @retval EFI_SUCCESS Password correct, Browser will prompt for new\r
- password.\r
- @retval EFI_NOT_READY Password incorrect, Browser will show error\r
- message.\r
- @retval Other Browser will do nothing.\r
- @return In state of BROWSER_STATE_SET_PASSWORD:\r
- @retval EFI_SUCCESS Set password success.\r
- @retval Other Set password failed.\r
-\r
-**/\r
-EFI_STATUS\r
-PasswordCallback (\r
- IN UI_MENU_SELECTION *Selection,\r
- IN UI_MENU_OPTION *MenuOption,\r
- IN CHAR16 *String\r
- )\r
-{\r
- EFI_STATUS Status;\r
- EFI_HII_CONFIG_ACCESS_PROTOCOL *ConfigAccess;\r
- EFI_BROWSER_ACTION_REQUEST ActionRequest;\r
- EFI_IFR_TYPE_VALUE IfrTypeValue;\r
-\r
- ConfigAccess = Selection->FormSet->ConfigAccess;\r
- if (ConfigAccess == NULL) {\r
- return EFI_UNSUPPORTED;\r
- }\r
-\r
- //\r
- // Prepare password string in HII database\r
- //\r
- if (String != NULL) {\r
- IfrTypeValue.string = NewString (String, Selection->FormSet->HiiHandle);\r
- } else {\r
- IfrTypeValue.string = 0;\r
- }\r
-\r
- //\r
- // Send password to Configuration Driver for validation\r
- //\r
- Status = ConfigAccess->Callback (\r
- ConfigAccess,\r
- EFI_BROWSER_ACTION_CHANGING,\r
- MenuOption->ThisTag->QuestionId,\r
- MenuOption->ThisTag->HiiValue.Type,\r
- &IfrTypeValue,\r
- &ActionRequest\r
- );\r
-\r
- //\r
- // Remove password string from HII database\r
- //\r
- if (String != NULL) {\r
- DeleteString (IfrTypeValue.string, Selection->FormSet->HiiHandle);\r
- }\r
-\r
- return Status;\r
-}\r
-\r
-\r
-/**\r
- Display error message for invalid password.\r
-\r
-**/\r
-VOID\r
-PasswordInvalid (\r
- VOID\r
- )\r
-{\r
- EFI_INPUT_KEY Key;\r
-\r
- //\r
- // Invalid password, prompt error message\r
- //\r
- do {\r
- CreateDialog (4, TRUE, 0, NULL, &Key, gEmptyString, gPassowordInvalid, gPressEnter, gEmptyString);\r
- } while (Key.UnicodeChar != CHAR_CARRIAGE_RETURN);\r
-}\r
-\r
-\r
-/**\r
- Process a Question's Option (whether selected or un-selected).\r
-\r
- @param Selection Pointer to UI_MENU_SELECTION.\r
- @param MenuOption The MenuOption for this Question.\r
- @param Selected TRUE: if Question is selected.\r
- @param OptionString Pointer of the Option String to be displayed.\r
-\r
- @retval EFI_SUCCESS Question Option process success.\r
- @retval Other Question Option process fail.\r
-\r
-**/\r
-EFI_STATUS\r
-ProcessOptions (\r
- IN UI_MENU_SELECTION *Selection,\r
- IN UI_MENU_OPTION *MenuOption,\r
- IN BOOLEAN Selected,\r
- OUT CHAR16 **OptionString\r
- )\r
-{\r
- EFI_STATUS Status;\r
- CHAR16 *StringPtr;\r
- CHAR16 *TempString;\r
- UINTN Index;\r
- FORM_BROWSER_STATEMENT *Question;\r
- CHAR16 FormattedNumber[21];\r
- UINT16 Number;\r
- CHAR16 Character[2];\r
- EFI_INPUT_KEY Key;\r
- UINTN BufferSize;\r
- QUESTION_OPTION *OneOfOption;\r
- LIST_ENTRY *Link;\r
- EFI_HII_VALUE HiiValue;\r
- EFI_HII_VALUE *QuestionValue;\r
- UINT16 Maximum;\r
- QUESTION_OPTION *Option;\r
- UINTN Index2;\r
- UINT8 *ValueArray;\r
- UINT8 ValueType;\r
- EFI_STRING_ID StringId;\r
-\r
- Status = EFI_SUCCESS;\r
-\r
- StringPtr = NULL;\r
- Character[1] = L'\0';\r
- *OptionString = NULL;\r
- StringId = 0;\r
-\r
- ZeroMem (FormattedNumber, 21 * sizeof (CHAR16));\r
- BufferSize = (gOptionBlockWidth + 1) * 2 * gScreenDimensions.BottomRow;\r
-\r
- Question = MenuOption->ThisTag;\r
- QuestionValue = &Question->HiiValue;\r
- Maximum = (UINT16) Question->Maximum;\r
-\r
- ValueArray = Question->BufferValue;\r
- ValueType = Question->ValueType;\r
-\r
- switch (Question->Operand) {\r
- case EFI_IFR_ORDERED_LIST_OP:\r
- //\r
- // Check whether there are Options of this OrderedList\r
- //\r
- if (IsListEmpty (&Question->OptionListHead)) {\r
- break;\r
- }\r
- //\r
- // Initialize Option value array\r
- //\r
- if (GetArrayData (ValueArray, ValueType, 0) == 0) {\r
- GetQuestionDefault (Selection->FormSet, Selection->Form, Question, 0);\r
- }\r
-\r
- if (Selected) {\r
- //\r
- // Go ask for input\r
- //\r
- Status = GetSelectionInputPopUp (Selection, MenuOption);\r
- } else {\r
- //\r
- // We now know how many strings we will have, so we can allocate the\r
- // space required for the array or strings.\r
- //\r
- *OptionString = AllocateZeroPool (Question->MaxContainers * BufferSize);\r
- ASSERT (*OptionString);\r
-\r
- HiiValue.Type = ValueType;\r
- HiiValue.Value.u64 = 0;\r
- for (Index = 0; Index < Question->MaxContainers; Index++) {\r
- HiiValue.Value.u64 = GetArrayData (ValueArray, ValueType, Index);\r
- if (HiiValue.Value.u64 == 0) {\r
- //\r
- // Values for the options in ordered lists should never be a 0\r
- //\r
- break;\r
- }\r
-\r
- OneOfOption = ValueToOption (Question, &HiiValue);\r
- if (OneOfOption == NULL) {\r
- //\r
- // Show error message\r
- //\r
- do {\r
- CreateDialog (4, TRUE, 0, NULL, &Key, gEmptyString, gOptionMismatch, gPressEnter, gEmptyString);\r
- } while (Key.UnicodeChar != CHAR_CARRIAGE_RETURN);\r
-\r
- //\r
- // The initial value of the orderedlist is invalid, force to be valid value\r
- //\r
- Link = GetFirstNode (&Question->OptionListHead);\r
- Index2 = 0;\r
- while (!IsNull (&Question->OptionListHead, Link) && Index2 < Question->MaxContainers) {\r
- Option = QUESTION_OPTION_FROM_LINK (Link);\r
- Link = GetNextNode (&Question->OptionListHead, Link);\r
- if ((Option->SuppressExpression != NULL) &&\r
- ((EvaluateExpressionList(Option->SuppressExpression, FALSE, NULL, NULL) == ExpressSuppress))) {\r
- continue;\r
- }\r
- SetArrayData (ValueArray, ValueType, Index2, Option->Value.Value.u64);\r
- Index2++;\r
- }\r
- SetArrayData (ValueArray, ValueType, Index2, 0);\r
-\r
- Status = SetQuestionValue (Selection->FormSet, Selection->Form, Question, GetSetValueWithEditBuffer);\r
- UpdateStatusBar (Selection, NV_UPDATE_REQUIRED, Question->QuestionFlags, TRUE);\r
-\r
- FreePool (*OptionString);\r
- *OptionString = NULL;\r
- return EFI_NOT_FOUND;\r
- }\r
-\r
- Character[0] = LEFT_ONEOF_DELIMITER;\r
- NewStrCat (OptionString[0], Character);\r
- StringPtr = GetToken (OneOfOption->Text, Selection->Handle);\r
- ASSERT (StringPtr != NULL);\r
- NewStrCat (OptionString[0], StringPtr);\r
- Character[0] = RIGHT_ONEOF_DELIMITER;\r
- NewStrCat (OptionString[0], Character);\r
- Character[0] = CHAR_CARRIAGE_RETURN;\r
- NewStrCat (OptionString[0], Character);\r
- FreePool (StringPtr);\r
- }\r
-\r
- //\r
- // Search the other options, try to find the one not in the container.\r
- //\r
- Link = GetFirstNode (&Question->OptionListHead);\r
- while (!IsNull (&Question->OptionListHead, Link)) {\r
- OneOfOption = QUESTION_OPTION_FROM_LINK (Link);\r
- Link = GetNextNode (&Question->OptionListHead, Link);\r
- if ((OneOfOption->SuppressExpression != NULL) &&\r
- ((EvaluateExpressionList(OneOfOption->SuppressExpression, FALSE, NULL, NULL) == ExpressSuppress))) {\r
- continue;\r
- }\r
-\r
- if (FindArrayData (ValueArray, ValueType, OneOfOption->Value.Value.u64, NULL)) {\r
- continue;\r
- }\r
-\r
- SetArrayData (ValueArray, ValueType, Index++, OneOfOption->Value.Value.u64);\r
-\r
- Character[0] = LEFT_ONEOF_DELIMITER;\r
- NewStrCat (OptionString[0], Character);\r
- StringPtr = GetToken (OneOfOption->Text, Selection->Handle);\r
- ASSERT (StringPtr != NULL);\r
- NewStrCat (OptionString[0], StringPtr);\r
- Character[0] = RIGHT_ONEOF_DELIMITER;\r
- NewStrCat (OptionString[0], Character);\r
- Character[0] = CHAR_CARRIAGE_RETURN;\r
- NewStrCat (OptionString[0], Character);\r
- FreePool (StringPtr);\r
- }\r
- }\r
- break;\r
-\r
- case EFI_IFR_ONE_OF_OP:\r
- //\r
- // Check whether there are Options of this OneOf\r
- //\r
- if (IsListEmpty (&Question->OptionListHead)) {\r
- break;\r
- }\r
- if (Selected) {\r
- //\r
- // Go ask for input\r
- //\r
- Status = GetSelectionInputPopUp (Selection, MenuOption);\r
- } else {\r
- *OptionString = AllocateZeroPool (BufferSize);\r
- ASSERT (*OptionString);\r
-\r
- OneOfOption = ValueToOption (Question, QuestionValue);\r
- if (OneOfOption == NULL) {\r
- //\r
- // Show error message\r
- //\r
- do {\r
- CreateDialog (4, TRUE, 0, NULL, &Key, gEmptyString, gOptionMismatch, gPressEnter, gEmptyString);\r
- } while (Key.UnicodeChar != CHAR_CARRIAGE_RETURN);\r
-\r
- //\r
- // Force the Question value to be valid\r
- //\r
- Link = GetFirstNode (&Question->OptionListHead);\r
- while (!IsNull (&Question->OptionListHead, Link)) {\r
- Option = QUESTION_OPTION_FROM_LINK (Link);\r
-\r
- if ((Option->SuppressExpression == NULL) ||\r
- (EvaluateExpressionList(Option->SuppressExpression, FALSE, NULL, NULL) == ExpressFalse)) {\r
- CopyMem (QuestionValue, &Option->Value, sizeof (EFI_HII_VALUE));\r
- SetQuestionValue (Selection->FormSet, Selection->Form, Question, GetSetValueWithEditBuffer);\r
- UpdateStatusBar (Selection, NV_UPDATE_REQUIRED, Question->QuestionFlags, TRUE);\r
- break;\r
- }\r
-\r
- Link = GetNextNode (&Question->OptionListHead, Link);\r
- }\r
-\r
- FreePool (*OptionString);\r
- *OptionString = NULL;\r
- return EFI_NOT_FOUND;\r
- }\r
-\r
- Character[0] = LEFT_ONEOF_DELIMITER;\r
- NewStrCat (OptionString[0], Character);\r
- StringPtr = GetToken (OneOfOption->Text, Selection->Handle);\r
- ASSERT (StringPtr != NULL);\r
- NewStrCat (OptionString[0], StringPtr);\r
- Character[0] = RIGHT_ONEOF_DELIMITER;\r
- NewStrCat (OptionString[0], Character);\r
-\r
- FreePool (StringPtr);\r
- }\r
- break;\r
-\r
- case EFI_IFR_CHECKBOX_OP:\r
- *OptionString = AllocateZeroPool (BufferSize);\r
- ASSERT (*OptionString);\r
-\r
- *OptionString[0] = LEFT_CHECKBOX_DELIMITER;\r
-\r
- if (Selected) {\r
- //\r
- // Since this is a BOOLEAN operation, flip it upon selection\r
- //\r
- QuestionValue->Value.b = (BOOLEAN) (QuestionValue->Value.b ? FALSE : TRUE);\r
-\r
- //\r
- // Perform inconsistent check\r
- //\r
- Status = ValidateQuestion (Selection->FormSet, Selection->Form, Question, EFI_HII_EXPRESSION_INCONSISTENT_IF);\r
- if (EFI_ERROR (Status)) {\r
- //\r
- // Inconsistent check fail, restore Question Value\r
- //\r
- QuestionValue->Value.b = (BOOLEAN) (QuestionValue->Value.b ? FALSE : TRUE);\r
- FreePool (*OptionString);\r
- *OptionString = NULL;\r
- return Status;\r
- }\r
-\r
- //\r
- // Save Question value\r
- //\r
- Status = SetQuestionValue (Selection->FormSet, Selection->Form, Question, GetSetValueWithEditBuffer);\r
- UpdateStatusBar (Selection, NV_UPDATE_REQUIRED, Question->QuestionFlags, TRUE);\r
- }\r
-\r
- if (QuestionValue->Value.b) {\r
- *(OptionString[0] + 1) = CHECK_ON;\r
- } else {\r
- *(OptionString[0] + 1) = CHECK_OFF;\r
- }\r
- *(OptionString[0] + 2) = RIGHT_CHECKBOX_DELIMITER;\r
- break;\r
-\r
- case EFI_IFR_NUMERIC_OP:\r
- if (Selected) {\r
- //\r
- // Go ask for input\r
- //\r
- Status = GetNumericInput (Selection, MenuOption);\r
- } else {\r
- *OptionString = AllocateZeroPool (BufferSize);\r
- ASSERT (*OptionString);\r
-\r
- *OptionString[0] = LEFT_NUMERIC_DELIMITER;\r
-\r
- //\r
- // Formatted print\r
- //\r
- PrintFormattedNumber (Question, FormattedNumber, 21 * sizeof (CHAR16));\r
- Number = (UINT16) GetStringWidth (FormattedNumber);\r
- CopyMem (OptionString[0] + 1, FormattedNumber, Number);\r
-\r
- *(OptionString[0] + Number / 2) = RIGHT_NUMERIC_DELIMITER;\r
- }\r
- break;\r
-\r
- case EFI_IFR_DATE_OP:\r
- if (Selected) {\r
- //\r
- // This is similar to numerics\r
- //\r
- Status = GetNumericInput (Selection, MenuOption);\r
- } else {\r
- *OptionString = AllocateZeroPool (BufferSize);\r
- ASSERT (*OptionString);\r
-\r
- switch (MenuOption->Sequence) {\r
- case 0:\r
- *OptionString[0] = LEFT_NUMERIC_DELIMITER;\r
- UnicodeSPrint (OptionString[0] + 1, 21 * sizeof (CHAR16), L"%02d", QuestionValue->Value.date.Month);\r
- *(OptionString[0] + 3) = DATE_SEPARATOR;\r
- break;\r
-\r
- case 1:\r
- SetUnicodeMem (OptionString[0], 4, L' ');\r
- UnicodeSPrint (OptionString[0] + 4, 21 * sizeof (CHAR16), L"%02d", QuestionValue->Value.date.Day);\r
- *(OptionString[0] + 6) = DATE_SEPARATOR;\r
- break;\r
-\r
- case 2:\r
- SetUnicodeMem (OptionString[0], 7, L' ');\r
- UnicodeSPrint (OptionString[0] + 7, 21 * sizeof (CHAR16), L"%04d", QuestionValue->Value.date.Year);\r
- *(OptionString[0] + 11) = RIGHT_NUMERIC_DELIMITER;\r
- break;\r
- }\r
- }\r
- break;\r
-\r
- case EFI_IFR_TIME_OP:\r
- if (Selected) {\r
- //\r
- // This is similar to numerics\r
- //\r
- Status = GetNumericInput (Selection, MenuOption);\r
- } else {\r
- *OptionString = AllocateZeroPool (BufferSize);\r
- ASSERT (*OptionString);\r
-\r
- switch (MenuOption->Sequence) {\r
- case 0:\r
- *OptionString[0] = LEFT_NUMERIC_DELIMITER;\r
- UnicodeSPrint (OptionString[0] + 1, 21 * sizeof (CHAR16), L"%02d", QuestionValue->Value.time.Hour);\r
- *(OptionString[0] + 3) = TIME_SEPARATOR;\r
- break;\r
-\r
- case 1:\r
- SetUnicodeMem (OptionString[0], 4, L' ');\r
- UnicodeSPrint (OptionString[0] + 4, 21 * sizeof (CHAR16), L"%02d", QuestionValue->Value.time.Minute);\r
- *(OptionString[0] + 6) = TIME_SEPARATOR;\r
- break;\r
-\r
- case 2:\r
- SetUnicodeMem (OptionString[0], 7, L' ');\r
- UnicodeSPrint (OptionString[0] + 7, 21 * sizeof (CHAR16), L"%02d", QuestionValue->Value.time.Second);\r
- *(OptionString[0] + 9) = RIGHT_NUMERIC_DELIMITER;\r
- break;\r
- }\r
- }\r
- break;\r
-\r
- case EFI_IFR_STRING_OP:\r
- if (Selected) {\r
- StringPtr = AllocateZeroPool ((Maximum + 1) * sizeof (CHAR16));\r
- ASSERT (StringPtr);\r
- CopyMem(StringPtr, Question->BufferValue, Maximum * sizeof (CHAR16));\r
-\r
- Status = ReadString (MenuOption, gPromptForData, StringPtr);\r
- if (!EFI_ERROR (Status)) {\r
- HiiSetString(Selection->FormSet->HiiHandle, Question->HiiValue.Value.string, StringPtr, NULL);\r
- Status = ValidateQuestion(Selection->FormSet, Selection->Form, Question, EFI_HII_EXPRESSION_INCONSISTENT_IF);\r
- if (EFI_ERROR (Status)) {\r
- HiiSetString(Selection->FormSet->HiiHandle, Question->HiiValue.Value.string, (CHAR16*)Question->BufferValue, NULL);\r
- } else {\r
- CopyMem (Question->BufferValue, StringPtr, Maximum * sizeof (CHAR16));\r
- SetQuestionValue (Selection->FormSet, Selection->Form, Question, GetSetValueWithEditBuffer);\r
-\r
- UpdateStatusBar (Selection, NV_UPDATE_REQUIRED, Question->QuestionFlags, TRUE);\r
- }\r
- }\r
-\r
- FreePool (StringPtr);\r
- } else {\r
- *OptionString = AllocateZeroPool (BufferSize);\r
- ASSERT (*OptionString);\r
-\r
- if (((CHAR16 *) Question->BufferValue)[0] == 0x0000) {\r
- *(OptionString[0]) = '_';\r
- } else {\r
- if ((Maximum * sizeof (CHAR16)) < BufferSize) {\r
- BufferSize = Maximum * sizeof (CHAR16);\r
- }\r
- CopyMem (OptionString[0], (CHAR16 *) Question->BufferValue, BufferSize);\r
- }\r
- }\r
- break;\r
-\r
- case EFI_IFR_PASSWORD_OP:\r
- if (Selected) {\r
- StringPtr = AllocateZeroPool ((Maximum + 1) * sizeof (CHAR16));\r
- ASSERT (StringPtr);\r
-\r
- //\r
- // For interactive passwords, old password is validated by callback\r
- //\r
- if ((Question->QuestionFlags & EFI_IFR_FLAG_CALLBACK) != 0) {\r
- //\r
- // Use a NULL password to test whether old password is required\r
- //\r
- *StringPtr = 0;\r
- Status = PasswordCallback (Selection, MenuOption, StringPtr);\r
- if (Status == EFI_NOT_AVAILABLE_YET || Status == EFI_UNSUPPORTED) {\r
- //\r
- // Callback is not supported, or\r
- // Callback request to terminate password input\r
- //\r
- FreePool (StringPtr);\r
- return EFI_SUCCESS;\r
- }\r
-\r
- if (EFI_ERROR (Status)) {\r
- //\r
- // Old password exist, ask user for the old password\r
- //\r
- Status = ReadString (MenuOption, gPromptForPassword, StringPtr);\r
- if (EFI_ERROR (Status)) {\r
- FreePool (StringPtr);\r
- return Status;\r
- }\r
-\r
- //\r
- // Check user input old password\r
- //\r
- Status = PasswordCallback (Selection, MenuOption, StringPtr);\r
- if (EFI_ERROR (Status)) {\r
- if (Status == EFI_NOT_READY) {\r
- //\r
- // Typed in old password incorrect\r
- //\r
- PasswordInvalid ();\r
- } else {\r
- Status = EFI_SUCCESS;\r
- }\r
-\r
- FreePool (StringPtr);\r
- return Status;\r
- }\r
- }\r
- } else {\r
- //\r
- // For non-interactive password, validate old password in local\r
- //\r
- if (*((CHAR16 *) Question->BufferValue) != 0) {\r
- //\r
- // There is something there! Prompt for password\r
- //\r
- Status = ReadString (MenuOption, gPromptForPassword, StringPtr);\r
- if (EFI_ERROR (Status)) {\r
- FreePool (StringPtr);\r
- return Status;\r
- }\r
-\r
- TempString = AllocateCopyPool ((Maximum + 1) * sizeof (CHAR16), Question->BufferValue);\r
- ASSERT (TempString != NULL);\r
-\r
- TempString[Maximum] = L'\0';\r
-\r
- if (StrCmp (StringPtr, TempString) != 0) {\r
- //\r
- // Typed in old password incorrect\r
- //\r
- PasswordInvalid ();\r
-\r
- FreePool (StringPtr);\r
- FreePool (TempString);\r
- return Status;\r
- }\r
-\r
- FreePool (TempString);\r
- }\r
- }\r
-\r
- //\r
- // Ask for new password\r
- //\r
- ZeroMem (StringPtr, (Maximum + 1) * sizeof (CHAR16));\r
- Status = ReadString (MenuOption, gPromptForNewPassword, StringPtr);\r
- if (EFI_ERROR (Status)) {\r
- //\r
- // Reset state machine for interactive password\r
- //\r
- if ((Question->QuestionFlags & EFI_IFR_FLAG_CALLBACK) != 0) {\r
- PasswordCallback (Selection, MenuOption, NULL);\r
- }\r
-\r
- FreePool (StringPtr);\r
- return Status;\r
- }\r
-\r
- //\r
- // Confirm new password\r
- //\r
- TempString = AllocateZeroPool ((Maximum + 1) * sizeof (CHAR16));\r
- ASSERT (TempString);\r
- Status = ReadString (MenuOption, gConfirmPassword, TempString);\r
- if (EFI_ERROR (Status)) {\r
- //\r
- // Reset state machine for interactive password\r
- //\r
- if ((Question->QuestionFlags & EFI_IFR_FLAG_CALLBACK) != 0) {\r
- PasswordCallback (Selection, MenuOption, NULL);\r
- }\r
-\r
- FreePool (StringPtr);\r
- FreePool (TempString);\r
- return Status;\r
- }\r
-\r
- //\r
- // Compare two typed-in new passwords\r
- //\r
- if (StrCmp (StringPtr, TempString) == 0) {\r
- //\r
- // Prepare the Question->HiiValue.Value.string for ValidateQuestion use.\r
- //\r
- if((Question->QuestionFlags & EFI_IFR_FLAG_CALLBACK) != 0) {\r
- StringId = Question->HiiValue.Value.string;\r
- Question->HiiValue.Value.string = NewString (StringPtr, Selection->FormSet->HiiHandle);\r
- } else {\r
- HiiSetString(Selection->FormSet->HiiHandle, Question->HiiValue.Value.string, StringPtr, NULL);\r
- }\r
- \r
- Status = ValidateQuestion(Selection->FormSet, Selection->Form, Question, EFI_HII_EXPRESSION_INCONSISTENT_IF);\r
-\r
- //\r
- // Researve the Question->HiiValue.Value.string.\r
- //\r
- if((Question->QuestionFlags & EFI_IFR_FLAG_CALLBACK) != 0) {\r
- DeleteString(Question->HiiValue.Value.string, Selection->FormSet->HiiHandle);\r
- Question->HiiValue.Value.string = StringId;\r
- } \r
- \r
- if (EFI_ERROR (Status)) {\r
- //\r
- // Reset state machine for interactive password\r
- //\r
- if ((Question->QuestionFlags & EFI_IFR_FLAG_CALLBACK) != 0) {\r
- PasswordCallback (Selection, MenuOption, NULL);\r
- } else {\r
- //\r
- // Researve the Question->HiiValue.Value.string.\r
- //\r
- HiiSetString(Selection->FormSet->HiiHandle, Question->HiiValue.Value.string, (CHAR16*)Question->BufferValue, NULL); \r
- }\r
- } else {\r
- //\r
- // Two password match, send it to Configuration Driver\r
- //\r
- if ((Question->QuestionFlags & EFI_IFR_FLAG_CALLBACK) != 0) {\r
- PasswordCallback (Selection, MenuOption, StringPtr);\r
- } else {\r
- CopyMem (Question->BufferValue, StringPtr, Maximum * sizeof (CHAR16));\r
- SetQuestionValue (Selection->FormSet, Selection->Form, Question, GetSetValueWithHiiDriver);\r
- }\r
- }\r
- } else {\r
- //\r
- // Reset state machine for interactive password\r
- //\r
- if ((Question->QuestionFlags & EFI_IFR_FLAG_CALLBACK) != 0) {\r
- PasswordCallback (Selection, MenuOption, NULL);\r
- }\r
-\r
- //\r
- // Two password mismatch, prompt error message\r
- //\r
- do {\r
- CreateDialog (4, TRUE, 0, NULL, &Key, gEmptyString, gConfirmError, gPressEnter, gEmptyString);\r
- } while (Key.UnicodeChar != CHAR_CARRIAGE_RETURN);\r
- }\r
-\r
- FreePool (TempString);\r
- FreePool (StringPtr);\r
- }\r
- break;\r
-\r
- default:\r
- break;\r
- }\r
-\r
- return Status;\r
-}\r
-\r
-\r
-/**\r
- Process the help string: Split StringPtr to several lines of strings stored in\r
- FormattedString and the glyph width of each line cannot exceed gHelpBlockWidth.\r
-\r
- @param StringPtr The entire help string.\r
- @param FormattedString The oupput formatted string.\r
- @param EachLineWidth The max string length of each line in the formatted string.\r
- @param RowCount TRUE: if Question is selected.\r
-\r
-**/\r
-UINTN\r
-ProcessHelpString (\r
- IN CHAR16 *StringPtr,\r
- OUT CHAR16 **FormattedString,\r
- OUT UINT16 *EachLineWidth,\r
- IN UINTN RowCount\r
- )\r
-{\r
- UINTN Index;\r
- CHAR16 *OutputString;\r
- UINTN TotalRowNum;\r
- UINTN CheckedNum;\r
- UINT16 GlyphWidth;\r
- UINT16 LineWidth;\r
- UINT16 MaxStringLen;\r
- UINT16 StringLen;\r
-\r
- TotalRowNum = 0;\r
- CheckedNum = 0;\r
- GlyphWidth = 1;\r
- Index = 0;\r
- MaxStringLen = 0;\r
- StringLen = 0;\r
-\r
- //\r
- // Set default help string width.\r
- //\r
- LineWidth = (UINT16) (gHelpBlockWidth - 1);\r
-\r
- //\r
- // Get row number of the String.\r
- //\r
- while ((StringLen = GetLineByWidth (StringPtr, LineWidth, &GlyphWidth, &Index, &OutputString)) != 0) {\r
- if (StringLen > MaxStringLen) {\r
- MaxStringLen = StringLen;\r
- }\r
-\r
- TotalRowNum ++;\r
- FreePool (OutputString);\r
- }\r
- *EachLineWidth = MaxStringLen;\r
-\r
- *FormattedString = AllocateZeroPool (TotalRowNum * MaxStringLen * sizeof (CHAR16));\r
- ASSERT (*FormattedString != NULL);\r
-\r
- //\r
- // Generate formatted help string array.\r
- //\r
- GlyphWidth = 1;\r
- Index = 0;\r
- while((StringLen = GetLineByWidth (StringPtr, LineWidth, &GlyphWidth, &Index, &OutputString)) != 0) {\r
- CopyMem (*FormattedString + CheckedNum * MaxStringLen, OutputString, StringLen * sizeof (CHAR16));\r
- CheckedNum ++;\r
- FreePool (OutputString);\r
- }\r
-\r
- return TotalRowNum; \r
-}\r
RegisterHotKey,\r
RegiserExitHandler,\r
SaveReminder\r
+ },\r
+ {\r
+ BROWSER_EXTENSION2_VERSION_1,\r
+ SetScope,\r
+ RegisterHotKey,\r
+ RegiserExitHandler,\r
+ IsBrowserDataModified,\r
+ ExecuteAction,\r
}\r
};\r
\r
EFI_HII_DATABASE_PROTOCOL *mHiiDatabase;\r
-EFI_HII_STRING_PROTOCOL *mHiiString;\r
EFI_HII_CONFIG_ROUTING_PROTOCOL *mHiiConfigRouting;\r
EFI_DEVICE_PATH_FROM_TEXT_PROTOCOL *mPathFromText;\r
+EDKII_FORM_DISPLAY_ENGINE_PROTOCOL *mFormDisplay;\r
\r
UINTN gBrowserContextCount = 0;\r
LIST_ENTRY gBrowserContextList = INITIALIZE_LIST_HEAD_VARIABLE (gBrowserContextList);\r
LIST_ENTRY gBrowserFormSetList = INITIALIZE_LIST_HEAD_VARIABLE (gBrowserFormSetList);\r
LIST_ENTRY gBrowserHotKeyList = INITIALIZE_LIST_HEAD_VARIABLE (gBrowserHotKeyList);\r
-LIST_ENTRY gBrowserStorageList = INITIALIZE_LIST_HEAD_VARIABLE (gBrowserStorageList);\r
+LIST_ENTRY gBrowserStorageList = INITIALIZE_LIST_HEAD_VARIABLE (gBrowserStorageList);\r
\r
-BANNER_DATA *gBannerData;\r
-EFI_HII_HANDLE gFrontPageHandle;\r
-UINTN gClassOfVfr;\r
-UINTN gFunctionKeySetting;\r
BOOLEAN gResetRequired;\r
-EFI_HII_HANDLE gHiiHandle;\r
-UINT16 gDirection;\r
-EFI_SCREEN_DESCRIPTOR gScreenDimensions;\r
+BOOLEAN gExitRequired;\r
BROWSER_SETTING_SCOPE gBrowserSettingScope = FormSetLevel;\r
BOOLEAN mBrowserScopeFirstSet = TRUE;\r
EXIT_HANDLER ExitHandlerFunction = NULL;\r
-UINTN gFooterHeight;\r
\r
//\r
// Browser Global Strings\r
//\r
-CHAR16 *gSaveFailed;\r
-CHAR16 *gDiscardFailed;\r
-CHAR16 *gDefaultFailed;\r
-CHAR16 *gEnterString;\r
-CHAR16 *gEnterCommitString;\r
-CHAR16 *gEnterEscapeString;\r
-CHAR16 *gEscapeString;\r
-CHAR16 *gMoveHighlight;\r
-CHAR16 *gMakeSelection;\r
-CHAR16 *gDecNumericInput;\r
-CHAR16 *gHexNumericInput;\r
-CHAR16 *gToggleCheckBox;\r
-CHAR16 *gPromptForData;\r
-CHAR16 *gPromptForPassword;\r
-CHAR16 *gPromptForNewPassword;\r
-CHAR16 *gConfirmPassword;\r
-CHAR16 *gConfirmError;\r
-CHAR16 *gPassowordInvalid;\r
-CHAR16 *gPressEnter;\r
CHAR16 *gEmptyString;\r
-CHAR16 *gAreYouSure;\r
-CHAR16 *gYesResponse;\r
-CHAR16 *gNoResponse;\r
-CHAR16 *gMiniString;\r
-CHAR16 *gPlusString;\r
-CHAR16 *gMinusString;\r
-CHAR16 *gAdjustNumber;\r
-CHAR16 *gSaveChanges;\r
-CHAR16 *gOptionMismatch;\r
-CHAR16 *gFormSuppress;\r
-CHAR16 *gProtocolNotFound;\r
-\r
CHAR16 *mUnknownString = L"!";\r
\r
-CHAR16 gPromptBlockWidth;\r
-CHAR16 gOptionBlockWidth;\r
-CHAR16 gHelpBlockWidth;\r
-\r
EFI_GUID gZeroGuid = {0, 0, 0, {0, 0, 0, 0, 0, 0, 0, 0}};\r
-EFI_GUID gSetupBrowserGuid = {\r
- 0xab368524, 0xb60c, 0x495b, {0xa0, 0x9, 0x12, 0xe8, 0x5b, 0x1a, 0xea, 0x32}\r
-};\r
\r
-FORM_BROWSER_FORMSET *gOldFormSet = NULL;\r
+extern UINT32 gBrowserStatus;\r
+extern CHAR16 *gErrorInfo;\r
+extern EFI_GUID mCurrentFormSetGuid;\r
+extern EFI_HII_HANDLE mCurrentHiiHandle;\r
+extern UINT16 mCurrentFormId;\r
+extern FORM_DISPLAY_ENGINE_FORM gDisplayFormData;\r
+\r
+/**\r
+ Create a menu with specified formset GUID and form ID, and add it as a child\r
+ of the given parent menu.\r
+\r
+ @param HiiHandle Hii handle related to this formset.\r
+ @param FormSetGuid The Formset Guid of menu to be added.\r
+ @param FormId The Form ID of menu to be added.\r
+ @param QuestionId The question id of this menu to be added.\r
+\r
+ @return A pointer to the newly added menu or NULL if memory is insufficient.\r
+\r
+**/\r
+FORM_ENTRY_INFO *\r
+UiAddMenuList (\r
+ IN EFI_HII_HANDLE HiiHandle,\r
+ IN EFI_GUID *FormSetGuid,\r
+ IN UINT16 FormId,\r
+ IN UINT16 QuestionId\r
+ )\r
+{\r
+ FORM_ENTRY_INFO *MenuList;\r
+\r
+ MenuList = AllocateZeroPool (sizeof (FORM_ENTRY_INFO));\r
+ if (MenuList == NULL) {\r
+ return NULL;\r
+ }\r
+\r
+ MenuList->Signature = FORM_ENTRY_INFO_SIGNATURE;\r
+\r
+ MenuList->HiiHandle = HiiHandle;\r
+ CopyMem (&MenuList->FormSetGuid, FormSetGuid, sizeof (EFI_GUID));\r
+ MenuList->FormId = FormId;\r
+ MenuList->QuestionId = QuestionId;\r
\r
-FUNCTIION_KEY_SETTING gFunctionKeySettingTable[] = {\r
//\r
- // Boot Manager\r
+ // If parent is not specified, it is the root Form of a Formset\r
//\r
- {\r
- {\r
- 0x847bc3fe,\r
- 0xb974,\r
- 0x446d,\r
- {\r
- 0x94,\r
- 0x49,\r
- 0x5a,\r
- 0xd5,\r
- 0x41,\r
- 0x2e,\r
- 0x99,\r
- 0x3b\r
+ InsertTailList (&mPrivateData.FormBrowserEx2.FormViewHistoryHead, &MenuList->Link);\r
+\r
+ return MenuList;\r
+}\r
+\r
+/**\r
+ Return the form id for the input hiihandle and formset.\r
+\r
+ @param HiiHandle HiiHandle for FormSet.\r
+ @param FormSetGuid The Formset GUID of the menu to search.\r
+\r
+ @return First form's id for this form set.\r
+\r
+**/\r
+EFI_FORM_ID\r
+GetFirstFormId (\r
+ IN EFI_HII_HANDLE HiiHandle,\r
+ IN EFI_GUID *FormSetGuid\r
+ )\r
+{\r
+ LIST_ENTRY *Link;\r
+ FORM_BROWSER_FORM *Form;\r
+\r
+ Link = GetFirstNode (&gCurrentSelection->FormSet->FormListHead);\r
+ Form = FORM_BROWSER_FORM_FROM_LINK (Link);\r
+\r
+ return Form->FormId;\r
+}\r
+\r
+/**\r
+ Search Menu with given FormSetGuid and FormId in all cached menu list.\r
+\r
+ @param HiiHandle HiiHandle for FormSet.\r
+ @param FormSetGuid The Formset GUID of the menu to search.\r
+ @param FormId The Form ID of menu to search.\r
+\r
+ @return A pointer to menu found or NULL if not found.\r
+\r
+**/\r
+FORM_ENTRY_INFO *\r
+UiFindMenuList (\r
+ IN EFI_HII_HANDLE HiiHandle, \r
+ IN EFI_GUID *FormSetGuid,\r
+ IN UINT16 FormId\r
+ )\r
+{\r
+ LIST_ENTRY *Link;\r
+ FORM_ENTRY_INFO *MenuList;\r
+ FORM_ENTRY_INFO *RetMenu;\r
+ EFI_FORM_ID FirstFormId;\r
+\r
+ RetMenu = NULL;\r
+\r
+ Link = GetFirstNode (&mPrivateData.FormBrowserEx2.FormViewHistoryHead);\r
+ while (!IsNull (&mPrivateData.FormBrowserEx2.FormViewHistoryHead, Link)) {\r
+ MenuList = FORM_ENTRY_INFO_FROM_LINK (Link);\r
+ Link = GetNextNode (&mPrivateData.FormBrowserEx2.FormViewHistoryHead, Link);\r
+ \r
+ //\r
+ // If already find the menu, free the menus behind it.\r
+ //\r
+ if (RetMenu != NULL) {\r
+ RemoveEntryList (&MenuList->Link);\r
+ FreePool (MenuList);\r
+ continue;\r
+ }\r
+\r
+ //\r
+ // Find the same FromSet.\r
+ //\r
+ if (MenuList->HiiHandle == HiiHandle) {\r
+ if (CompareGuid (&MenuList->FormSetGuid, &gZeroGuid)) {\r
+ //\r
+ // FormSetGuid is not specified.\r
+ //\r
+ RetMenu = MenuList;\r
+ } else if (CompareGuid (&MenuList->FormSetGuid, FormSetGuid)) {\r
+ if (MenuList->FormId == FormId) {\r
+ RetMenu = MenuList;\r
+ } else if (FormId == 0 || MenuList->FormId == 0 ) {\r
+ FirstFormId = GetFirstFormId (HiiHandle, FormSetGuid);\r
+ if ((FormId == 0 && FirstFormId == MenuList->FormId) || (MenuList->FormId ==0 && FirstFormId == FormId)) {\r
+ RetMenu = MenuList;\r
+ }\r
+ }\r
}\r
- },\r
- NONE_FUNCTION_KEY_SETTING\r
- },\r
+ }\r
+ }\r
+\r
+ return RetMenu;\r
+}\r
+\r
+/**\r
+ Find parent menu for current menu.\r
+\r
+ @param CurrentMenu Current Menu\r
+\r
+ @retval The parent menu for current menu.\r
+**/\r
+FORM_ENTRY_INFO *\r
+UiFindParentMenu (\r
+ IN FORM_ENTRY_INFO *CurrentMenu\r
+ )\r
+{\r
+ FORM_ENTRY_INFO *ParentMenu;\r
+\r
+ ParentMenu = NULL;\r
+ if (CurrentMenu->Link.BackLink != &mPrivateData.FormBrowserEx2.FormViewHistoryHead) {\r
+ ParentMenu = FORM_ENTRY_INFO_FROM_LINK (CurrentMenu->Link.BackLink);\r
+ }\r
+\r
+ return ParentMenu;\r
+}\r
+\r
+/**\r
+ Free Menu list linked list.\r
+\r
+ @param MenuListHead One Menu list point in the menu list.\r
+\r
+**/\r
+VOID\r
+UiFreeMenuList (\r
+ LIST_ENTRY *MenuListHead\r
+ )\r
+{\r
+ FORM_ENTRY_INFO *MenuList;\r
+\r
+ while (!IsListEmpty (MenuListHead)) {\r
+ MenuList = FORM_ENTRY_INFO_FROM_LINK (MenuListHead->ForwardLink);\r
+ RemoveEntryList (&MenuList->Link);\r
+\r
+ FreePool (MenuList);\r
+ }\r
+}\r
+\r
+/**\r
+ Load all hii formset to the browser.\r
+\r
+**/\r
+VOID\r
+LoadAllHiiFormset (\r
+ VOID\r
+ )\r
+{\r
+ FORM_BROWSER_FORMSET *LocalFormSet;\r
+ EFI_HII_HANDLE *HiiHandles;\r
+ UINTN Index;\r
+ EFI_GUID ZeroGuid;\r
+ EFI_STATUS Status;\r
+\r
//\r
- // Device Manager\r
+ // Get all the Hii handles\r
//\r
- {\r
- {\r
- 0x3ebfa8e6,\r
- 0x511d,\r
- 0x4b5b,\r
- {\r
- 0xa9,\r
- 0x5f,\r
- 0xfb,\r
- 0x38,\r
- 0x26,\r
- 0xf,\r
- 0x1c,\r
- 0x27\r
- }\r
- },\r
- NONE_FUNCTION_KEY_SETTING\r
- },\r
+ HiiHandles = HiiGetHiiHandles (NULL);\r
+ ASSERT (HiiHandles != NULL);\r
+\r
//\r
- // BMM FormSet.\r
+ // Search for formset of each class type\r
//\r
- {\r
- {\r
- 0x642237c7,\r
- 0x35d4,\r
- 0x472d,\r
- {\r
- 0x83,\r
- 0x65,\r
- 0x12,\r
- 0xe0,\r
- 0xcc,\r
- 0xf2,\r
- 0x7a,\r
- 0x22\r
- }\r
- },\r
- NONE_FUNCTION_KEY_SETTING\r
- },\r
+ for (Index = 0; HiiHandles[Index] != NULL; Index++) {\r
+ //\r
+ // Check HiiHandles[Index] does exist in global maintain list.\r
+ //\r
+ if (GetFormSetFromHiiHandle (HiiHandles[Index]) != NULL) {\r
+ continue;\r
+ }\r
+\r
+ //\r
+ // Initilize FormSet Setting\r
+ //\r
+ LocalFormSet = AllocateZeroPool (sizeof (FORM_BROWSER_FORMSET));\r
+ ASSERT (LocalFormSet != NULL);\r
+ ZeroMem (&ZeroGuid, sizeof (ZeroGuid));\r
+ Status = InitializeFormSet (HiiHandles[Index], &ZeroGuid, LocalFormSet);\r
+ if (EFI_ERROR (Status) || IsListEmpty (&LocalFormSet->FormListHead)) {\r
+ DestroyFormSet (LocalFormSet);\r
+ continue;\r
+ }\r
+ InitializeCurrentSetting (LocalFormSet);\r
+\r
+ //\r
+ // Initilize Questions' Value\r
+ //\r
+ Status = LoadFormSetConfig (NULL, LocalFormSet);\r
+ if (EFI_ERROR (Status)) {\r
+ DestroyFormSet (LocalFormSet);\r
+ continue;\r
+ }\r
+ }\r
+\r
//\r
- // BMM File Explorer FormSet.\r
+ // Free resources, and restore gOldFormSet and gClassOfVfr\r
//\r
- {\r
- {\r
- 0x1f2d63e1,\r
- 0xfebd,\r
- 0x4dc7,\r
- {\r
- 0x9c,\r
- 0xc5,\r
- 0xba,\r
- 0x2b,\r
- 0x1c,\r
- 0xef,\r
- 0x9c,\r
- 0x5b\r
- }\r
- },\r
- NONE_FUNCTION_KEY_SETTING\r
- },\r
-};\r
+ FreePool (HiiHandles);\r
+}\r
\r
/**\r
This is the routine which an external caller uses to direct the browser\r
UI_MENU_SELECTION *Selection;\r
UINTN Index;\r
FORM_BROWSER_FORMSET *FormSet;\r
- LIST_ENTRY *Link;\r
+ FORM_ENTRY_INFO *MenuList;\r
\r
//\r
- // Calculate total number of Register HotKeys. \r
+ // If EDKII_FORM_DISPLAY_ENGINE_PROTOCOL not found, return EFI_UNSUPPORTED.\r
//\r
- Index = 0;\r
- Link = GetFirstNode (&gBrowserHotKeyList);\r
- while (!IsNull (&gBrowserHotKeyList, Link)) {\r
- Link = GetNextNode (&gBrowserHotKeyList, Link);\r
- Index ++;\r
+ if (mFormDisplay == NULL) {\r
+ return EFI_UNSUPPORTED;\r
}\r
- //\r
- // Show three HotKeys help information on one ROW.\r
- //\r
- gFooterHeight = FOOTER_HEIGHT + (Index / 3);\r
-\r
- //\r
- // Clean the history menu list.\r
- //\r
- InitializeListHead (&gMenuList);\r
\r
//\r
// Save globals used by SendForm()\r
SaveBrowserContext ();\r
\r
gResetRequired = FALSE;\r
- Status = EFI_SUCCESS;\r
- ZeroMem (&gScreenDimensions, sizeof (EFI_SCREEN_DESCRIPTOR));\r
-\r
- //\r
- // Seed the dimensions in the global\r
- //\r
- gST->ConOut->QueryMode (\r
- gST->ConOut,\r
- gST->ConOut->Mode->Mode,\r
- &gScreenDimensions.RightColumn,\r
- &gScreenDimensions.BottomRow\r
- );\r
-\r
- if (ScreenDimensions != NULL) {\r
- //\r
- // Check local dimension vs. global dimension.\r
- //\r
- if ((gScreenDimensions.RightColumn < ScreenDimensions->RightColumn) ||\r
- (gScreenDimensions.BottomRow < ScreenDimensions->BottomRow)\r
- ) {\r
- Status = EFI_INVALID_PARAMETER;\r
- goto Done;\r
- } else {\r
- //\r
- // Local dimension validation.\r
- //\r
- if ((ScreenDimensions->RightColumn > ScreenDimensions->LeftColumn) &&\r
- (ScreenDimensions->BottomRow > ScreenDimensions->TopRow) &&\r
- ((ScreenDimensions->RightColumn - ScreenDimensions->LeftColumn) > 2) &&\r
- (\r
- (ScreenDimensions->BottomRow - ScreenDimensions->TopRow) > STATUS_BAR_HEIGHT +\r
- SCROLL_ARROW_HEIGHT *\r
- 2 +\r
- FRONT_PAGE_HEADER_HEIGHT +\r
- gFooterHeight +\r
- 1\r
- )\r
- ) {\r
- CopyMem (&gScreenDimensions, (VOID *) ScreenDimensions, sizeof (EFI_SCREEN_DESCRIPTOR));\r
- } else {\r
- Status = EFI_INVALID_PARAMETER;\r
- goto Done;\r
- }\r
- }\r
- }\r
-\r
- gOptionBlockWidth = (CHAR16) ((gScreenDimensions.RightColumn - gScreenDimensions.LeftColumn) / 3);\r
- gPromptBlockWidth = (CHAR16) (gOptionBlockWidth + LEFT_SKIPPED_COLUMNS);\r
- gHelpBlockWidth = (CHAR16) (gOptionBlockWidth - LEFT_SKIPPED_COLUMNS);\r
-\r
- //\r
- // Initialize the strings for the browser, upon exit of the browser, the strings will be freed\r
- //\r
- InitializeBrowserStrings ();\r
-\r
- //\r
- // Ensure we are in Text mode\r
- //\r
- gST->ConOut->SetAttribute (gST->ConOut, EFI_TEXT_ATTR (EFI_LIGHTGRAY, EFI_BLACK));\r
+ gExitRequired = FALSE;\r
+ Status = EFI_SUCCESS;\r
+ gEmptyString = L"";\r
+ gDisplayFormData.ScreenDimensions = (EFI_SCREEN_DESCRIPTOR *) ScreenDimensions;\r
\r
for (Index = 0; Index < HandleCount; Index++) {\r
Selection = AllocateZeroPool (sizeof (UI_MENU_SELECTION));\r
//\r
// Initialize internal data structures of FormSet\r
//\r
- Status = InitializeFormSet (Selection->Handle, &Selection->FormSetGuid, FormSet, TRUE);\r
+ Status = InitializeFormSet (Selection->Handle, &Selection->FormSetGuid, FormSet);\r
if (EFI_ERROR (Status) || IsListEmpty (&FormSet->FormListHead)) {\r
DestroyFormSet (FormSet);\r
break;\r
}\r
Selection->FormSet = FormSet;\r
\r
- //\r
- // Try to find pre FormSet in the maintain backup list.\r
- //\r
- gOldFormSet = GetFormSetFromHiiHandle (Selection->Handle);\r
-\r
//\r
// Display this formset\r
//\r
\r
gCurrentSelection = NULL;\r
\r
- if (EFI_ERROR (Status)) {\r
- break;\r
- }\r
-\r
- } while (Selection->Action == UI_ACTION_REFRESH_FORMSET);\r
-\r
- if (gOldFormSet != NULL) {\r
//\r
// If no data is changed, don't need to save current FormSet into the maintain list.\r
//\r
- if (!IsNvUpdateRequired (gOldFormSet)) {\r
- CleanBrowserStorage(gOldFormSet);\r
- RemoveEntryList (&gOldFormSet->Link);\r
- DestroyFormSet (gOldFormSet);\r
+ if (!IsNvUpdateRequiredForFormSet (FormSet) && !IsStorageDataChangedForFormSet(FormSet)) {\r
+ CleanBrowserStorage(FormSet);\r
+ RemoveEntryList (&FormSet->Link);\r
+ DestroyFormSet (FormSet);\r
}\r
- gOldFormSet = NULL;\r
- }\r
+\r
+ if (EFI_ERROR (Status)) {\r
+ break;\r
+ }\r
+ } while (Selection->Action == UI_ACTION_REFRESH_FORMSET);\r
\r
FreePool (Selection);\r
}\r
\r
+ //\r
+ // Still has error info, pop up a message.\r
+ //\r
+ if (gBrowserStatus != BROWSER_SUCCESS) {\r
+ gDisplayFormData.BrowserStatus = gBrowserStatus;\r
+ gDisplayFormData.ErrorString = gErrorInfo;\r
+\r
+ gBrowserStatus = BROWSER_SUCCESS;\r
+ gErrorInfo = NULL;\r
+\r
+ mFormDisplay->FormDisplay (&gDisplayFormData, NULL);\r
+ }\r
+\r
if (ActionRequest != NULL) {\r
*ActionRequest = EFI_BROWSER_ACTION_REQUEST_NONE;\r
if (gResetRequired) {\r
}\r
}\r
\r
- FreeBrowserStrings ();\r
- UiFreeMenuList(&gMenuList);\r
+ mFormDisplay->ExitDisplay();\r
\r
- gST->ConOut->SetAttribute (gST->ConOut, EFI_TEXT_ATTR (EFI_LIGHTGRAY, EFI_BLACK));\r
- gST->ConOut->ClearScreen (gST->ConOut);\r
+ //\r
+ // Clear the menu history data.\r
+ //\r
+ while (!IsListEmpty (&mPrivateData.FormBrowserEx2.FormViewHistoryHead)) {\r
+ MenuList = FORM_ENTRY_INFO_FROM_LINK (mPrivateData.FormBrowserEx2.FormViewHistoryHead.ForwardLink);\r
+ RemoveEntryList (&MenuList->Link);\r
+ FreePool (MenuList);\r
+ }\r
\r
-Done:\r
//\r
// Restore globals used by SendForm()\r
//\r
return Status;\r
}\r
\r
+/**\r
+ Get or set data to the storage.\r
+\r
+ @param ResultsDataSize The size of the buffer associatedwith ResultsData.\r
+ @param ResultsData A string returned from an IFR browser or\r
+ equivalent. The results string will have no\r
+ routing information in them.\r
+ @param RetrieveData A BOOLEAN field which allows an agent to retrieve\r
+ (if RetrieveData = TRUE) data from the uncommitted\r
+ browser state information or set (if RetrieveData\r
+ = FALSE) data in the uncommitted browser state\r
+ information.\r
+ @param Storage The pointer to the storage.\r
+\r
+ @retval EFI_SUCCESS The results have been distributed or are awaiting\r
+ distribution.\r
+\r
+**/\r
+EFI_STATUS \r
+ProcessStorage (\r
+ IN OUT UINTN *ResultsDataSize,\r
+ IN OUT EFI_STRING *ResultsData,\r
+ IN BOOLEAN RetrieveData,\r
+ IN BROWSER_STORAGE *Storage\r
+ )\r
+{\r
+ CHAR16 *ConfigResp;\r
+ EFI_STATUS Status;\r
+ CHAR16 *StrPtr;\r
+ UINTN BufferSize;\r
+ UINTN TmpSize;\r
+\r
+ if (RetrieveData) {\r
+ //\r
+ // Generate <ConfigResp>\r
+ //\r
+ Status = StorageToConfigResp (Storage, &ConfigResp, Storage->ConfigRequest, TRUE);\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ //\r
+ // Skip <ConfigHdr> and '&' to point to <ConfigBody> when first copy the configbody.\r
+ // Also need to consider add "\0" at first time.\r
+ //\r
+ StrPtr = ConfigResp + StrLen (Storage->ConfigHdr) + 1;\r
+ BufferSize = StrSize (StrPtr);\r
+\r
+\r
+ //\r
+ // Copy the data if the input buffer is bigger enough.\r
+ //\r
+ if (*ResultsDataSize >= BufferSize) {\r
+ StrCpy (*ResultsData, StrPtr);\r
+ }\r
+\r
+ *ResultsDataSize = BufferSize;\r
+ FreePool (ConfigResp);\r
+ } else {\r
+ //\r
+ // Prepare <ConfigResp>\r
+ //\r
+ TmpSize = StrLen (*ResultsData);\r
+ BufferSize = (TmpSize + StrLen (Storage->ConfigHdr) + 2) * sizeof (CHAR16);\r
+ ConfigResp = AllocateZeroPool (BufferSize);\r
+ ASSERT (ConfigResp != NULL);\r
+\r
+ StrCpy (ConfigResp, Storage->ConfigHdr);\r
+ StrCat (ConfigResp, L"&");\r
+ StrCat (ConfigResp, *ResultsData);\r
+\r
+ //\r
+ // Update Browser uncommited data\r
+ //\r
+ Status = ConfigRespToStorage (Storage, ConfigResp);\r
+ FreePool (ConfigResp);\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+ }\r
+\r
+ return EFI_SUCCESS;\r
+}\r
\r
/**\r
- This function is called by a callback handler to retrieve uncommitted state\r
- data from the browser.\r
+ This routine called this service in the browser to retrieve or set certain uncommitted \r
+ state information that resides in the open formsets. \r
\r
@param This A pointer to the EFI_FORM_BROWSER2_PROTOCOL\r
instance.\r
{\r
EFI_STATUS Status;\r
LIST_ENTRY *Link;\r
- FORMSET_STORAGE *Storage;\r
+ BROWSER_STORAGE *Storage;\r
+ FORMSET_STORAGE *FormsetStorage;\r
FORM_BROWSER_FORMSET *FormSet;\r
+ UINTN TotalSize;\r
BOOLEAN Found;\r
- CHAR16 *ConfigResp;\r
- CHAR16 *StrPtr;\r
- UINTN BufferSize;\r
- UINTN TmpSize;\r
\r
if (ResultsDataSize == NULL || ResultsData == NULL) {\r
return EFI_INVALID_PARAMETER;\r
}\r
\r
- if (gCurrentSelection == NULL) {\r
- return EFI_NOT_READY;\r
- }\r
-\r
- Storage = NULL;\r
- ConfigResp = NULL;\r
- FormSet = gCurrentSelection->FormSet;\r
+ TotalSize = *ResultsDataSize;\r
+ Storage = NULL;\r
+ Found = FALSE;\r
+ Status = EFI_SUCCESS;\r
\r
//\r
- // Find target storage\r
+ // If set browser data, pre load all hii formset to avoid set the varstore which is not \r
+ // saved in browser.\r
//\r
- Link = GetFirstNode (&FormSet->StorageListHead);\r
- if (IsNull (&FormSet->StorageListHead, Link)) {\r
- return EFI_UNSUPPORTED;\r
+ if (!RetrieveData && (gBrowserSettingScope == SystemLevel)) {\r
+ LoadAllHiiFormset();\r
}\r
\r
if (VariableGuid != NULL) {\r
//\r
- // Try to find target storage\r
+ // Try to find target storage in the current formset.\r
//\r
- Found = FALSE;\r
- while (!IsNull (&FormSet->StorageListHead, Link)) {\r
- Storage = FORMSET_STORAGE_FROM_LINK (Link);\r
- Link = GetNextNode (&FormSet->StorageListHead, Link);\r
+ Link = GetFirstNode (&gBrowserStorageList);\r
+ while (!IsNull (&gBrowserStorageList, Link)) {\r
+ Storage = BROWSER_STORAGE_FROM_LINK (Link);\r
+ Link = GetNextNode (&gBrowserStorageList, Link);\r
+ //\r
+ // Check the current storage.\r
+ //\r
+ if (!CompareGuid (&Storage->Guid, (EFI_GUID *) VariableGuid)) {\r
+ continue;\r
+ }\r
\r
- if (CompareGuid (&Storage->BrowserStorage->Guid, (EFI_GUID *) VariableGuid)) {\r
- if (Storage->BrowserStorage->Type == EFI_HII_VARSTORE_BUFFER ||\r
- Storage->BrowserStorage->Type == EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER) {\r
- //\r
- // Buffer storage require both GUID and Name\r
- //\r
- if (VariableName == NULL) {\r
- return EFI_NOT_FOUND;\r
- }\r
+ if (Storage->Type == EFI_HII_VARSTORE_BUFFER ||\r
+ Storage->Type == EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER) {\r
+ //\r
+ // Buffer storage require both GUID and Name\r
+ //\r
+ if (VariableName == NULL) {\r
+ return EFI_NOT_FOUND;\r
+ }\r
\r
- if (StrCmp (Storage->BrowserStorage->Name, (CHAR16 *) VariableName) != 0) {\r
- continue;\r
- }\r
+ if (StrCmp (Storage->Name, (CHAR16 *) VariableName) != 0) {\r
+ continue;\r
}\r
- Found = TRUE;\r
- break;\r
}\r
+\r
+ Status = ProcessStorage (&TotalSize, &ResultsData, RetrieveData, Storage);\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ //\r
+ // Different formsets may have same varstore, so here just set the flag\r
+ // not exit the circle.\r
+ // \r
+ Found = TRUE;\r
+ break;\r
}\r
\r
if (!Found) {\r
//\r
// GUID/Name is not specified, take the first storage in FormSet\r
//\r
- Storage = FORMSET_STORAGE_FROM_LINK (Link);\r
- }\r
-\r
- if (RetrieveData) {\r
- //\r
- // Skip if there is no RequestElement\r
- //\r
- if (Storage->ElementCount == 0) {\r
- return EFI_SUCCESS;\r
+ if (gCurrentSelection == NULL) {\r
+ return EFI_NOT_READY;\r
}\r
\r
//\r
// Generate <ConfigResp>\r
//\r
- Status = StorageToConfigResp (Storage->BrowserStorage, &ConfigResp, Storage->ConfigRequest);\r
+ FormSet = gCurrentSelection->FormSet;\r
+ Link = GetFirstNode (&FormSet->StorageListHead);\r
+ if (IsNull (&FormSet->StorageListHead, Link)) {\r
+ return EFI_UNSUPPORTED;\r
+ }\r
+\r
+ FormsetStorage = FORMSET_STORAGE_FROM_LINK (Link);\r
+ \r
+ Status = ProcessStorage (&TotalSize, &ResultsData, RetrieveData, FormsetStorage->BrowserStorage);\r
if (EFI_ERROR (Status)) {\r
return Status;\r
}\r
+ }\r
\r
- //\r
- // Skip <ConfigHdr> and '&' to point to <ConfigBody>\r
- //\r
- StrPtr = ConfigResp + StrLen (Storage->BrowserStorage->ConfigHdr) + 1;\r
+ if (RetrieveData) {\r
+ Status = TotalSize <= *ResultsDataSize ? EFI_SUCCESS : EFI_BUFFER_TOO_SMALL;\r
+ *ResultsDataSize = TotalSize;\r
+ }\r
+ \r
+ return Status;\r
\r
- BufferSize = StrSize (StrPtr);\r
- if (*ResultsDataSize < BufferSize) {\r
- *ResultsDataSize = BufferSize;\r
+}\r
\r
- FreePool (ConfigResp);\r
- return EFI_BUFFER_TOO_SMALL;\r
- }\r
\r
- *ResultsDataSize = BufferSize;\r
- CopyMem (ResultsData, StrPtr, BufferSize);\r
+/**\r
+ Callback function for SimpleTextInEx protocol install events\r
\r
- FreePool (ConfigResp);\r
- } else {\r
- //\r
- // Prepare <ConfigResp>\r
- //\r
- TmpSize = StrLen (ResultsData);\r
- BufferSize = (TmpSize + StrLen (Storage->BrowserStorage->ConfigHdr) + 2) * sizeof (CHAR16);\r
- ConfigResp = AllocateZeroPool (BufferSize);\r
- ASSERT (ConfigResp != NULL);\r
+ @param Event the event that is signaled.\r
+ @param Context not used here.\r
\r
- StrCpy (ConfigResp, Storage->BrowserStorage->ConfigHdr);\r
- StrCat (ConfigResp, L"&");\r
- StrCat (ConfigResp, ResultsData);\r
+**/\r
+VOID\r
+EFIAPI\r
+FormDisplayCallback (\r
+ IN EFI_EVENT Event,\r
+ IN VOID *Context\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
\r
- //\r
- // Update Browser uncommited data\r
- //\r
- Status = ConfigRespToStorage (Storage->BrowserStorage, ConfigResp);\r
- if (EFI_ERROR (Status)) {\r
- return Status;\r
- }\r
+ if (mFormDisplay != NULL) {\r
+ return;\r
}\r
\r
- return EFI_SUCCESS;\r
+ Status = gBS->LocateProtocol (\r
+ &gEdkiiFormDisplayEngineProtocolGuid,\r
+ NULL,\r
+ (VOID **) &mFormDisplay\r
+ );\r
}\r
\r
/**\r
)\r
{\r
EFI_STATUS Status;\r
- EFI_INPUT_KEY DefaultHotKey;\r
- EFI_STRING HelpString;\r
+ VOID *Registration;\r
\r
//\r
// Locate required Hii relative protocols\r
);\r
ASSERT_EFI_ERROR (Status);\r
\r
- Status = gBS->LocateProtocol (\r
- &gEfiHiiStringProtocolGuid,\r
- NULL,\r
- (VOID **) &mHiiString\r
- );\r
- ASSERT_EFI_ERROR (Status);\r
-\r
Status = gBS->LocateProtocol (\r
&gEfiHiiConfigRoutingProtocolGuid,\r
NULL,\r
(VOID **) &mPathFromText\r
);\r
\r
- //\r
- // Publish our HII data\r
- //\r
- gHiiHandle = HiiAddPackages (\r
- &gSetupBrowserGuid,\r
- ImageHandle,\r
- SetupBrowserStrings,\r
- NULL\r
- );\r
- ASSERT (gHiiHandle != NULL);\r
-\r
- //\r
- // Initialize Driver private data\r
- //\r
- gBannerData = AllocateZeroPool (sizeof (BANNER_DATA));\r
- ASSERT (gBannerData != NULL);\r
- \r
- //\r
- // Initialize generic help strings.\r
- //\r
- gSaveFailed = GetToken (STRING_TOKEN (SAVE_FAILED), gHiiHandle);\r
- gDiscardFailed = GetToken (STRING_TOKEN (DISCARD_FAILED), gHiiHandle);\r
- gDefaultFailed = GetToken (STRING_TOKEN (DEFAULT_FAILED), gHiiHandle);\r
-\r
//\r
// Install FormBrowser2 protocol\r
//\r
ASSERT_EFI_ERROR (Status);\r
\r
//\r
- // Install default HotKey F10 for Save\r
- //\r
- DefaultHotKey.UnicodeChar = CHAR_NULL;\r
- HelpString = GetToken (STRING_TOKEN (FUNCTION_TEN_STRING), gHiiHandle);\r
- DefaultHotKey.ScanCode = SCAN_F10;\r
- RegisterHotKey (&DefaultHotKey, BROWSER_ACTION_SUBMIT, 0, HelpString);\r
- FreePool (HelpString);\r
- //\r
- // Install default HotKey F9 for Reset To Defaults\r
- //\r
- DefaultHotKey.ScanCode = SCAN_F9;\r
- HelpString = GetToken (STRING_TOKEN (FUNCTION_NINE_STRING), gHiiHandle);\r
- RegisterHotKey (&DefaultHotKey, BROWSER_ACTION_DEFAULT, EFI_HII_DEFAULT_CLASS_STANDARD, HelpString);\r
- FreePool (HelpString);\r
-\r
- //\r
- // Install FormBrowserEx protocol\r
+ // Install FormBrowserEx2 protocol\r
//\r
+ InitializeListHead (&mPrivateData.FormBrowserEx2.FormViewHistoryHead); \r
mPrivateData.Handle = NULL;\r
+ Status = gBS->InstallProtocolInterface (\r
+ &mPrivateData.Handle,\r
+ &gEdkiiFormBrowserEx2ProtocolGuid,\r
+ EFI_NATIVE_INTERFACE,\r
+ &mPrivateData.FormBrowserEx2\r
+ );\r
+ ASSERT_EFI_ERROR (Status);\r
+ \r
Status = gBS->InstallProtocolInterface (\r
&mPrivateData.Handle,\r
&gEfiFormBrowserExProtocolGuid,\r
);\r
ASSERT_EFI_ERROR (Status);\r
\r
- return Status;\r
+ InitializeDisplayFormData ();\r
+\r
+ Status = gBS->LocateProtocol (\r
+ &gEdkiiFormDisplayEngineProtocolGuid,\r
+ NULL,\r
+ (VOID **) &mFormDisplay\r
+ );\r
+\r
+ if (EFI_ERROR (Status)) {\r
+ EfiCreateProtocolNotifyEvent (\r
+ &gEdkiiFormDisplayEngineProtocolGuid,\r
+ TPL_CALLBACK,\r
+ FormDisplayCallback,\r
+ NULL,\r
+ &Registration\r
+ );\r
+ }\r
+ \r
+ return EFI_SUCCESS;\r
}\r
\r
\r
*Dest = NewString;\r
}\r
\r
-\r
-/**\r
- Synchronize or restore Storage's Edit copy and Shadow copy.\r
-\r
- @param Storage The Storage to be synchronized.\r
- @param SyncOrRestore Sync the buffer to editbuffer or Restore the \r
- editbuffer to buffer\r
- if TRUE, copy the editbuffer to the buffer.\r
- if FALSE, copy the buffer to the editbuffer.\r
-\r
-**/\r
-VOID\r
-SynchronizeStorage (\r
- IN BROWSER_STORAGE *Storage,\r
- IN BOOLEAN SyncOrRestore\r
- )\r
-{\r
- LIST_ENTRY *Link;\r
- NAME_VALUE_NODE *Node;\r
-\r
- switch (Storage->Type) {\r
- case EFI_HII_VARSTORE_BUFFER:\r
- case EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER:\r
- if (SyncOrRestore) {\r
- CopyMem (Storage->Buffer, Storage->EditBuffer, Storage->Size);\r
- } else {\r
- CopyMem (Storage->EditBuffer, Storage->Buffer, Storage->Size);\r
- }\r
- break;\r
-\r
- case EFI_HII_VARSTORE_NAME_VALUE:\r
- Link = GetFirstNode (&Storage->NameValueListHead);\r
- while (!IsNull (&Storage->NameValueListHead, Link)) {\r
- Node = NAME_VALUE_NODE_FROM_LINK (Link);\r
-\r
- if (SyncOrRestore) {\r
- NewStringCpy (&Node->Value, Node->EditValue);\r
- } else {\r
- NewStringCpy (&Node->EditValue, Node->Value);\r
- }\r
-\r
- Link = GetNextNode (&Storage->NameValueListHead, Link);\r
- }\r
- break;\r
-\r
- case EFI_HII_VARSTORE_EFI_VARIABLE:\r
- default:\r
- break;\r
- }\r
-}\r
-\r
-\r
/**\r
Get Value for given Name from a NameValue Storage.\r
\r
@param Name The Name.\r
@param Value The Value to set.\r
@param SetValueTo Whether update editValue or Value.\r
+ @param ReturnNode The node use the input name.\r
\r
@retval EFI_SUCCESS Value found for given Name.\r
@retval EFI_NOT_FOUND No such Name found in NameValue storage.\r
**/\r
EFI_STATUS\r
SetValueByName (\r
- IN BROWSER_STORAGE *Storage,\r
- IN CHAR16 *Name,\r
- IN CHAR16 *Value,\r
- IN GET_SET_QUESTION_VALUE_WITH SetValueTo\r
+ IN BROWSER_STORAGE *Storage,\r
+ IN CHAR16 *Name,\r
+ IN CHAR16 *Value,\r
+ IN GET_SET_QUESTION_VALUE_WITH SetValueTo,\r
+ OUT NAME_VALUE_NODE **ReturnNode\r
)\r
{\r
LIST_ENTRY *Link;\r
} else {\r
Node->Value = Buffer;\r
}\r
+\r
+ if (ReturnNode != NULL) {\r
+ *ReturnNode = Node;\r
+ }\r
+\r
return EFI_SUCCESS;\r
}\r
\r
@param Storage The Storage to be conveted.\r
@param ConfigResp The returned <ConfigResp>.\r
@param ConfigRequest The ConfigRequest string.\r
+ @param GetEditBuf Get the data from editbuffer or buffer.\r
\r
@retval EFI_SUCCESS Convert success.\r
@retval EFI_INVALID_PARAMETER Incorrect storage type.\r
StorageToConfigResp (\r
IN BROWSER_STORAGE *Storage,\r
IN CHAR16 **ConfigResp,\r
- IN CHAR16 *ConfigRequest\r
+ IN CHAR16 *ConfigRequest,\r
+ IN BOOLEAN GetEditBuf\r
)\r
{\r
EFI_STATUS Status;\r
EFI_STRING Progress;\r
LIST_ENTRY *Link;\r
NAME_VALUE_NODE *Node;\r
+ UINT8 *SourceBuf;\r
\r
Status = EFI_SUCCESS;\r
\r
switch (Storage->Type) {\r
case EFI_HII_VARSTORE_BUFFER:\r
case EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER:\r
+ SourceBuf = GetEditBuf ? Storage->EditBuffer : Storage->Buffer;\r
Status = mHiiConfigRouting->BlockToConfig (\r
mHiiConfigRouting,\r
ConfigRequest,\r
- Storage->EditBuffer,\r
+ SourceBuf,\r
Storage->Size,\r
ConfigResp,\r
&Progress\r
NewStringCat (ConfigResp, L"&");\r
NewStringCat (ConfigResp, Node->Name);\r
NewStringCat (ConfigResp, L"=");\r
- NewStringCat (ConfigResp, Node->EditValue);\r
+ if (GetEditBuf) {\r
+ NewStringCat (ConfigResp, Node->EditValue);\r
+ } else {\r
+ NewStringCat (ConfigResp, Node->Value);\r
+ }\r
}\r
Link = GetNextNode (&Storage->NameValueListHead, Link);\r
}\r
if (StrPtr != NULL) {\r
*StrPtr = 0;\r
}\r
- SetValueByName (Storage, Name, Value, GetSetValueWithEditBuffer);\r
+ SetValueByName (Storage, Name, Value, GetSetValueWithEditBuffer, NULL);\r
}\r
break;\r
\r
if (IsBufferStorage) {\r
CopyMem (Storage->EditBuffer + Question->VarStoreInfo.VarOffset, Dst, StorageWidth);\r
} else {\r
- SetValueByName (Storage, Question->VariableName, Value, GetSetValueWithEditBuffer);\r
+ SetValueByName (Storage, Question->VariableName, Value, GetSetValueWithEditBuffer, NULL);\r
}\r
\r
if (Result != NULL) {\r
CHAR16 *TemName;\r
CHAR16 *TemString;\r
UINTN Index;\r
+ NAME_VALUE_NODE *Node;\r
\r
Status = EFI_SUCCESS;\r
+ Node = NULL;\r
\r
if (SetValueTo >= GetSetValueWithMax) {\r
return EFI_INVALID_PARAMETER;\r
// \r
CopyMem (Storage->Buffer + Question->VarStoreInfo.VarOffset, Src, StorageWidth);\r
}\r
+ //\r
+ // Check whether question value has been changed.\r
+ //\r
+ if (CompareMem (Storage->Buffer + Question->VarStoreInfo.VarOffset, Storage->EditBuffer + Question->VarStoreInfo.VarOffset, StorageWidth) != 0) {\r
+ Question->ValueChanged = TRUE;\r
+ } else {\r
+ Question->ValueChanged = FALSE;\r
+ }\r
} else {\r
if (IsString) {\r
//\r
}\r
}\r
\r
- Status = SetValueByName (Storage, Question->VariableName, Value, SetValueTo);\r
+ Status = SetValueByName (Storage, Question->VariableName, Value, SetValueTo, &Node);\r
FreePool (Value);\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+ //\r
+ // Check whether question value has been changed.\r
+ //\r
+ if (StrCmp (Node->Value, Node->EditValue) != 0) {\r
+ Question->ValueChanged = TRUE;\r
+ } else {\r
+ Question->ValueChanged = FALSE;\r
+ }\r
}\r
} else if (SetValueTo == GetSetValueWithHiiDriver) {\r
if (Storage->Type == EFI_HII_VARSTORE_BUFFER || Storage->Type == EFI_HII_VARSTORE_NAME_VALUE) {\r
\r
\r
/**\r
- Perform inconsistent check for a Form.\r
+ Perform nosubmitif check for a Form.\r
\r
@param FormSet FormSet data structure.\r
@param Form Form data structure.\r
@param Question The Question to be validated.\r
- @param Type Validation type: InConsistent or NoSubmit\r
+ @param Type Validation type: NoSubmit\r
\r
@retval EFI_SUCCESS Form validation pass.\r
@retval other Form validation failed.\r
LIST_ENTRY *Link;\r
LIST_ENTRY *ListHead;\r
EFI_STRING PopUp;\r
- EFI_INPUT_KEY Key;\r
FORM_EXPRESSION *Expression;\r
\r
- if (Type == EFI_HII_EXPRESSION_INCONSISTENT_IF) {\r
- ListHead = &Question->InconsistentListHead;\r
- } else if (Type == EFI_HII_EXPRESSION_NO_SUBMIT_IF) {\r
+ if (Type == EFI_HII_EXPRESSION_NO_SUBMIT_IF) {\r
ListHead = &Question->NoSubmitListHead;\r
} else {\r
return EFI_UNSUPPORTED;\r
//\r
if (Expression->Error != 0) {\r
PopUp = GetToken (Expression->Error, FormSet->HiiHandle);\r
- do {\r
- CreateDialog (4, TRUE, 0, NULL, &Key, gEmptyString, PopUp, gPressEnter, gEmptyString);\r
- } while (Key.UnicodeChar != CHAR_CARRIAGE_RETURN);\r
- FreePool (PopUp);\r
+ if (Type == EFI_HII_EXPRESSION_NO_SUBMIT_IF) {\r
+ gBrowserStatus = BROWSER_NO_SUBMIT_IF;\r
+ gErrorInfo = PopUp;\r
+ }\r
}\r
\r
return EFI_NOT_READY;\r
Fill storage's edit copy with settings requested from Configuration Driver.\r
\r
@param FormSet FormSet data structure.\r
- @param ConfigInfo The config info related to this form.\r
+ @param Storage The storage which need to sync.\r
+ @param ConfigRequest The config request string which used to sync storage.\r
@param SyncOrRestore Sync the buffer to editbuffer or Restore the \r
editbuffer to buffer\r
if TRUE, copy the editbuffer to the buffer.\r
\r
**/\r
EFI_STATUS\r
-SynchronizeStorageForForm (\r
- IN FORM_BROWSER_FORMSET *FormSet,\r
- IN FORM_BROWSER_CONFIG_REQUEST *ConfigInfo,\r
- IN BOOLEAN SyncOrRestore\r
+SynchronizeStorage (\r
+ IN FORM_BROWSER_FORMSET *FormSet,\r
+ OUT BROWSER_STORAGE *Storage,\r
+ IN CHAR16 *ConfigRequest,\r
+ IN BOOLEAN SyncOrRestore\r
)\r
{\r
EFI_STATUS Status;\r
\r
Status = EFI_SUCCESS;\r
Result = NULL;\r
- if (FormSet->ConfigAccess == NULL && ConfigInfo->Storage->Type != EFI_HII_VARSTORE_NAME_VALUE) {\r
- return EFI_NOT_FOUND;\r
- }\r
-\r
- if (ConfigInfo->ElementCount == 0) {\r
- //\r
- // Skip if there is no RequestElement\r
- //\r
- return EFI_SUCCESS;\r
- }\r
\r
- if (ConfigInfo->Storage->Type == EFI_HII_VARSTORE_BUFFER || \r
- (ConfigInfo->Storage->Type == EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER)) {\r
- BufferSize = ConfigInfo->Storage->Size;\r
+ if (Storage->Type == EFI_HII_VARSTORE_BUFFER || \r
+ (Storage->Type == EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER)) {\r
+ BufferSize = Storage->Size;\r
\r
if (SyncOrRestore) {\r
- Src = ConfigInfo->Storage->EditBuffer;\r
- Dst = ConfigInfo->Storage->Buffer;\r
+ Src = Storage->EditBuffer;\r
+ Dst = Storage->Buffer;\r
} else {\r
- Src = ConfigInfo->Storage->Buffer;\r
- Dst = ConfigInfo->Storage->EditBuffer;\r
+ Src = Storage->Buffer;\r
+ Dst = Storage->EditBuffer;\r
}\r
\r
- Status = mHiiConfigRouting->BlockToConfig(\r
- mHiiConfigRouting,\r
- ConfigInfo->ConfigRequest,\r
- Src,\r
- BufferSize,\r
- &Result,\r
- &Progress\r
- );\r
- if (EFI_ERROR (Status)) {\r
- return Status;\r
- }\r
+ if (ConfigRequest != NULL) {\r
+ Status = mHiiConfigRouting->BlockToConfig(\r
+ mHiiConfigRouting,\r
+ ConfigRequest,\r
+ Src,\r
+ BufferSize,\r
+ &Result,\r
+ &Progress\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
\r
- Status = mHiiConfigRouting->ConfigToBlock (\r
- mHiiConfigRouting,\r
- Result,\r
- Dst,\r
- &BufferSize,\r
- &Progress\r
- );\r
- if (Result != NULL) {\r
- FreePool (Result);\r
+ Status = mHiiConfigRouting->ConfigToBlock (\r
+ mHiiConfigRouting,\r
+ Result,\r
+ Dst,\r
+ &BufferSize,\r
+ &Progress\r
+ );\r
+ if (Result != NULL) {\r
+ FreePool (Result);\r
+ }\r
+ } else {\r
+ CopyMem (Dst, Src, BufferSize);\r
}\r
- } else if (ConfigInfo->Storage->Type == EFI_HII_VARSTORE_NAME_VALUE) {\r
- Link = GetFirstNode (&ConfigInfo->Storage->NameValueListHead);\r
- while (!IsNull (&ConfigInfo->Storage->NameValueListHead, Link)) {\r
+ } else if (Storage->Type == EFI_HII_VARSTORE_NAME_VALUE) {\r
+ Link = GetFirstNode (&Storage->NameValueListHead);\r
+ while (!IsNull (&Storage->NameValueListHead, Link)) {\r
Node = NAME_VALUE_NODE_FROM_LINK (Link);\r
\r
- if (StrStr (ConfigInfo->ConfigRequest, Node->Name) != NULL) {\r
+ if ((ConfigRequest != NULL && StrStr (ConfigRequest, Node->Name) != NULL) ||\r
+ (ConfigRequest == NULL)) {\r
if (SyncOrRestore) {\r
NewStringCpy (&Node->Value, Node->EditValue);\r
} else {\r
}\r
}\r
\r
- Link = GetNextNode (&ConfigInfo->Storage->NameValueListHead, Link);\r
+ Link = GetNextNode (&Storage->NameValueListHead, Link);\r
}\r
}\r
\r
{\r
LIST_ENTRY *Link;\r
FORM_BROWSER_STATEMENT *Question;\r
- EFI_STATUS Status;\r
- EFI_HII_VALUE HiiValue;\r
- UINT8 *BufferValue;\r
- BOOLEAN ValueChanged;\r
EFI_IFR_TYPE_VALUE *TypeValue;\r
EFI_BROWSER_ACTION_REQUEST ActionRequest;\r
\r
- ValueChanged = FALSE;\r
- BufferValue = NULL;\r
-\r
- if(!Form->NvUpdateRequired) {\r
- return;\r
- }\r
-\r
Link = GetFirstNode (&Form->StatementListHead);\r
while (!IsNull (&Form->StatementListHead, Link)) {\r
Question = FORM_BROWSER_STATEMENT_FROM_LINK (Link);\r
continue;\r
}\r
\r
- if (Question->BufferValue != NULL) {\r
- BufferValue = AllocateZeroPool (Question->StorageWidth);\r
- ASSERT (BufferValue != NULL);\r
- CopyMem (BufferValue, Question->BufferValue, Question->StorageWidth);\r
- } else {\r
- HiiValue.Type = Question->HiiValue.Type;\r
- CopyMem (&HiiValue.Value, &Question->HiiValue.Value, sizeof (EFI_IFR_TYPE_VALUE));\r
- }\r
-\r
- Status = GetQuestionValue (FormSet, Form, Question, GetSetValueWithBuffer);\r
- if (EFI_ERROR (Status)) {\r
- if (BufferValue != NULL) {\r
- FreePool (BufferValue);\r
- BufferValue = NULL;\r
- }\r
- continue;\r
- }\r
-\r
- if (Question->BufferValue != NULL) {\r
- if (CompareMem (BufferValue, Question->BufferValue, Question->StorageWidth)) {\r
- ValueChanged = TRUE;\r
- }\r
- } else {\r
- if (CompareMem (&HiiValue.Value, &Question->HiiValue.Value, sizeof (EFI_IFR_TYPE_VALUE))) {\r
- ValueChanged = TRUE;\r
- }\r
- }\r
-\r
- if (BufferValue != NULL) {\r
- FreePool (BufferValue);\r
- BufferValue = NULL;\r
- }\r
-\r
- if (!ValueChanged) {\r
+ if (!Question->ValueChanged) {\r
continue;\r
}\r
\r
- ValueChanged = FALSE;\r
-\r
if (Question->HiiValue.Type == EFI_IFR_TYPE_BUFFER) {\r
TypeValue = (EFI_IFR_TYPE_VALUE *) Question->BufferValue;\r
} else {\r
\r
return Find;\r
}\r
+/**\r
+ Check whether need to enable the reset flag in form level.\r
+ Also clean all ValueChanged flag in question.\r
+\r
+ @param SetFlag Whether need to set the Reset Flag.\r
+ @param Form Form data structure.\r
+\r
+**/\r
+VOID\r
+UpdateFlagForForm (\r
+ IN BOOLEAN SetFlag,\r
+ IN FORM_BROWSER_FORM *Form\r
+ )\r
+{\r
+ LIST_ENTRY *Link;\r
+ FORM_BROWSER_STATEMENT *Question;\r
+ BOOLEAN FindOne;\r
+\r
+ FindOne = FALSE;\r
+ Link = GetFirstNode (&Form->StatementListHead);\r
+ while (!IsNull (&Form->StatementListHead, Link)) {\r
+ Question = FORM_BROWSER_STATEMENT_FROM_LINK (Link);\r
+ \r
+ if (SetFlag && Question->ValueChanged && ((Question->QuestionFlags & EFI_IFR_FLAG_RESET_REQUIRED) != 0)) {\r
+ gResetRequired = TRUE;\r
+ } \r
+\r
+ if (Question->ValueChanged) {\r
+ Question->ValueChanged = FALSE;\r
+ }\r
+ \r
+ Link = GetNextNode (&Form->StatementListHead, Link);\r
+ }\r
+}\r
+\r
+/**\r
+ Check whether need to enable the reset flag.\r
+ Also clean ValueChanged flag for all statements.\r
+\r
+ Form level or formset level, only one.\r
+ \r
+ @param SetFlag Whether need to set the Reset Flag.\r
+ @param FormSet FormSet data structure.\r
+ @param Form Form data structure.\r
+\r
+**/\r
+VOID\r
+ValueChangeResetFlagUpdate (\r
+ IN BOOLEAN SetFlag,\r
+ IN FORM_BROWSER_FORMSET *FormSet,\r
+ IN FORM_BROWSER_FORM *Form \r
+ )\r
+{\r
+ FORM_BROWSER_FORM *CurrentForm;\r
+ LIST_ENTRY *Link;\r
+\r
+ //\r
+ // Form != NULL means only check form level.\r
+ //\r
+ if (Form != NULL) {\r
+ UpdateFlagForForm(SetFlag, Form);\r
+ return;\r
+ }\r
+\r
+ Link = GetFirstNode (&FormSet->FormListHead);\r
+ while (!IsNull (&FormSet->FormListHead, Link)) {\r
+ CurrentForm = FORM_BROWSER_FORM_FROM_LINK (Link);\r
+ Link = GetNextNode (&FormSet->FormListHead, Link);\r
+\r
+ UpdateFlagForForm(SetFlag, CurrentForm);\r
+ }\r
+}\r
\r
/**\r
Discard data based on the input setting scope (Form, FormSet or System).\r
return EFI_UNSUPPORTED;\r
}\r
\r
- if (SettingScope == FormLevel && Form->NvUpdateRequired) {\r
+ if (SettingScope == FormLevel && IsNvUpdateRequiredForForm (Form)) {\r
ConfigInfo = NULL;\r
Link = GetFirstNode (&Form->ConfigRequestHead);\r
while (!IsNull (&Form->ConfigRequestHead, Link)) {\r
//\r
// Prepare <ConfigResp>\r
//\r
- SynchronizeStorageForForm(FormSet, ConfigInfo, FALSE);\r
+ SynchronizeStorage(FormSet, ConfigInfo->Storage, ConfigInfo->ConfigRequest, FALSE);\r
\r
//\r
// Call callback with Changed type to inform the driver.\r
SendDiscardInfoToDriver (FormSet, Form);\r
}\r
\r
- Form->NvUpdateRequired = FALSE;\r
- } else if (SettingScope == FormSetLevel && IsNvUpdateRequired(FormSet)) {\r
+ ValueChangeResetFlagUpdate (FALSE, NULL, Form);\r
+ } else if (SettingScope == FormSetLevel && IsNvUpdateRequiredForFormSet (FormSet)) {\r
\r
//\r
// Discard Buffer storage or Name/Value storage\r
continue;\r
}\r
\r
- SynchronizeStorage(Storage->BrowserStorage, FALSE);\r
+ SynchronizeStorage(FormSet, Storage->BrowserStorage, Storage->ConfigRequest, FALSE);\r
}\r
\r
Link = GetFirstNode (&FormSet->FormListHead);\r
SendDiscardInfoToDriver (FormSet, Form);\r
}\r
\r
- UpdateNvInfoInForm (FormSet, FALSE); \r
+ ValueChangeResetFlagUpdate(FALSE, FormSet, NULL);\r
} else if (SettingScope == SystemLevel) {\r
//\r
// System Level Discard.\r
return Status;\r
}\r
\r
- if (SettingScope == FormLevel && Form->NvUpdateRequired) {\r
+ if (SettingScope == FormLevel && IsNvUpdateRequiredForForm (Form)) {\r
ConfigInfo = NULL;\r
Link = GetFirstNode (&Form->ConfigRequestHead);\r
while (!IsNull (&Form->ConfigRequestHead, Link)) {\r
//\r
// 1. Prepare <ConfigResp>\r
//\r
- Status = StorageToConfigResp (ConfigInfo->Storage, &ConfigResp, ConfigInfo->ConfigRequest);\r
+ Status = StorageToConfigResp (ConfigInfo->Storage, &ConfigResp, ConfigInfo->ConfigRequest, TRUE);\r
if (EFI_ERROR (Status)) {\r
return Status;\r
}\r
//\r
// 3. Config success, update storage shadow Buffer, only update the data belong to this form.\r
//\r
- SynchronizeStorageForForm(FormSet, ConfigInfo, TRUE);\r
+ SynchronizeStorage (FormSet, ConfigInfo->Storage, ConfigInfo->ConfigRequest, TRUE);\r
}\r
\r
//\r
// 4. Update the NV flag.\r
// \r
- Form->NvUpdateRequired = FALSE;\r
- } else if (SettingScope == FormSetLevel && IsNvUpdateRequired(FormSet)) {\r
+ ValueChangeResetFlagUpdate(TRUE, NULL, Form);\r
+ } else if (SettingScope == FormSetLevel && IsNvUpdateRequiredForFormSet (FormSet)) {\r
//\r
// Submit Buffer storage or Name/Value storage\r
//\r
//\r
// 1. Prepare <ConfigResp>\r
//\r
- Status = StorageToConfigResp (Storage, &ConfigResp, FormSetStorage->ConfigRequest);\r
+ Status = StorageToConfigResp (Storage, &ConfigResp, FormSetStorage->ConfigRequest, TRUE);\r
if (EFI_ERROR (Status)) {\r
return Status;\r
}\r
//\r
// 3. Config success, update storage shadow Buffer\r
//\r
- SynchronizeStorage (Storage, TRUE);\r
+ SynchronizeStorage (FormSet, Storage, FormSetStorage->ConfigRequest, TRUE);\r
}\r
\r
//\r
// 4. Update the NV flag.\r
// \r
- UpdateNvInfoInForm (FormSet, FALSE);\r
+ ValueChangeResetFlagUpdate(TRUE, FormSet, NULL);\r
} else if (SettingScope == SystemLevel) {\r
//\r
// System Level Save.\r
}\r
}\r
\r
-Done:\r
- if (ConfigRequest != NULL){\r
- FreePool (ConfigRequest);\r
- }\r
+Done:\r
+ if (ConfigRequest != NULL){\r
+ FreePool (ConfigRequest);\r
+ }\r
+\r
+ if (ConfigResp != NULL) {\r
+ FreePool (ConfigResp);\r
+ }\r
+ \r
+ if (Result != NULL) {\r
+ FreePool (Result);\r
+ }\r
+\r
+ return Status;\r
+}\r
+\r
+/**\r
+ Get default Id value used for browser.\r
+\r
+ @param DefaultId The default id value used by hii.\r
+\r
+ @retval Browser used default value.\r
+\r
+**/\r
+INTN\r
+GetDefaultIdForCallBack (\r
+ UINTN DefaultId\r
+ )\r
+{ \r
+ if (DefaultId == EFI_HII_DEFAULT_CLASS_STANDARD) {\r
+ return EFI_BROWSER_ACTION_DEFAULT_STANDARD;\r
+ } else if (DefaultId == EFI_HII_DEFAULT_CLASS_MANUFACTURING) {\r
+ return EFI_BROWSER_ACTION_DEFAULT_MANUFACTURING;\r
+ } else if (DefaultId == EFI_HII_DEFAULT_CLASS_SAFE) {\r
+ return EFI_BROWSER_ACTION_DEFAULT_SAFE;\r
+ } else if (DefaultId >= EFI_HII_DEFAULT_CLASS_PLATFORM_BEGIN && DefaultId < EFI_HII_DEFAULT_CLASS_PLATFORM_BEGIN + 0x1000) {\r
+ return EFI_BROWSER_ACTION_DEFAULT_PLATFORM + DefaultId - EFI_HII_DEFAULT_CLASS_PLATFORM_BEGIN;\r
+ } else if (DefaultId >= EFI_HII_DEFAULT_CLASS_HARDWARE_BEGIN && DefaultId < EFI_HII_DEFAULT_CLASS_HARDWARE_BEGIN + 0x1000) {\r
+ return EFI_BROWSER_ACTION_DEFAULT_HARDWARE + DefaultId - EFI_HII_DEFAULT_CLASS_HARDWARE_BEGIN;\r
+ } else if (DefaultId >= EFI_HII_DEFAULT_CLASS_FIRMWARE_BEGIN && DefaultId < EFI_HII_DEFAULT_CLASS_FIRMWARE_BEGIN + 0x1000) {\r
+ return EFI_BROWSER_ACTION_DEFAULT_FIRMWARE + DefaultId - EFI_HII_DEFAULT_CLASS_FIRMWARE_BEGIN;\r
+ } else {\r
+ return -1;\r
+ }\r
+}\r
+\r
+\r
+\r
+/**\r
+ Return data element in an Array by its Index.\r
+\r
+ @param Array The data array.\r
+ @param Type Type of the data in this array.\r
+ @param Index Zero based index for data in this array.\r
+\r
+ @retval Value The data to be returned\r
+\r
+**/\r
+UINT64\r
+GetArrayData (\r
+ IN VOID *Array,\r
+ IN UINT8 Type,\r
+ IN UINTN Index\r
+ )\r
+{\r
+ UINT64 Data;\r
+\r
+ ASSERT (Array != NULL);\r
+\r
+ Data = 0;\r
+ switch (Type) {\r
+ case EFI_IFR_TYPE_NUM_SIZE_8:\r
+ Data = (UINT64) *(((UINT8 *) Array) + Index);\r
+ break;\r
+\r
+ case EFI_IFR_TYPE_NUM_SIZE_16:\r
+ Data = (UINT64) *(((UINT16 *) Array) + Index);\r
+ break;\r
+\r
+ case EFI_IFR_TYPE_NUM_SIZE_32:\r
+ Data = (UINT64) *(((UINT32 *) Array) + Index);\r
+ break;\r
+\r
+ case EFI_IFR_TYPE_NUM_SIZE_64:\r
+ Data = (UINT64) *(((UINT64 *) Array) + Index);\r
+ break;\r
+\r
+ default:\r
+ break;\r
+ }\r
+\r
+ return Data;\r
+}\r
+\r
+\r
+/**\r
+ Set value of a data element in an Array by its Index.\r
+\r
+ @param Array The data array.\r
+ @param Type Type of the data in this array.\r
+ @param Index Zero based index for data in this array.\r
+ @param Value The value to be set.\r
\r
- if (ConfigResp != NULL) {\r
- FreePool (ConfigResp);\r
- }\r
- \r
- if (Result != NULL) {\r
- FreePool (Result);\r
- }\r
+**/\r
+VOID\r
+SetArrayData (\r
+ IN VOID *Array,\r
+ IN UINT8 Type,\r
+ IN UINTN Index,\r
+ IN UINT64 Value\r
+ )\r
+{\r
\r
- return Status;\r
+ ASSERT (Array != NULL);\r
+\r
+ switch (Type) {\r
+ case EFI_IFR_TYPE_NUM_SIZE_8:\r
+ *(((UINT8 *) Array) + Index) = (UINT8) Value;\r
+ break;\r
+\r
+ case EFI_IFR_TYPE_NUM_SIZE_16:\r
+ *(((UINT16 *) Array) + Index) = (UINT16) Value;\r
+ break;\r
+\r
+ case EFI_IFR_TYPE_NUM_SIZE_32:\r
+ *(((UINT32 *) Array) + Index) = (UINT32) Value;\r
+ break;\r
+\r
+ case EFI_IFR_TYPE_NUM_SIZE_64:\r
+ *(((UINT64 *) Array) + Index) = (UINT64) Value;\r
+ break;\r
+\r
+ default:\r
+ break;\r
+ }\r
}\r
\r
/**\r
- Get default Id value used for browser.\r
+ Search an Option of a Question by its value.\r
\r
- @param DefaultId The default id value used by hii.\r
+ @param Question The Question\r
+ @param OptionValue Value for Option to be searched.\r
\r
- @retval Browser used default value.\r
+ @retval Pointer Pointer to the found Option.\r
+ @retval NULL Option not found.\r
\r
**/\r
-INTN\r
-GetDefaultIdForCallBack (\r
- UINTN DefaultId\r
+QUESTION_OPTION *\r
+ValueToOption (\r
+ IN FORM_BROWSER_STATEMENT *Question,\r
+ IN EFI_HII_VALUE *OptionValue\r
)\r
-{ \r
- if (DefaultId == EFI_HII_DEFAULT_CLASS_STANDARD) {\r
- return EFI_BROWSER_ACTION_DEFAULT_STANDARD;\r
- } else if (DefaultId == EFI_HII_DEFAULT_CLASS_MANUFACTURING) {\r
- return EFI_BROWSER_ACTION_DEFAULT_MANUFACTURING;\r
- } else if (DefaultId == EFI_HII_DEFAULT_CLASS_SAFE) {\r
- return EFI_BROWSER_ACTION_DEFAULT_SAFE;\r
- } else if (DefaultId >= EFI_HII_DEFAULT_CLASS_PLATFORM_BEGIN && DefaultId < EFI_HII_DEFAULT_CLASS_PLATFORM_BEGIN + 0x1000) {\r
- return EFI_BROWSER_ACTION_DEFAULT_PLATFORM + DefaultId - EFI_HII_DEFAULT_CLASS_PLATFORM_BEGIN;\r
- } else if (DefaultId >= EFI_HII_DEFAULT_CLASS_HARDWARE_BEGIN && DefaultId < EFI_HII_DEFAULT_CLASS_HARDWARE_BEGIN + 0x1000) {\r
- return EFI_BROWSER_ACTION_DEFAULT_HARDWARE + DefaultId - EFI_HII_DEFAULT_CLASS_HARDWARE_BEGIN;\r
- } else if (DefaultId >= EFI_HII_DEFAULT_CLASS_FIRMWARE_BEGIN && DefaultId < EFI_HII_DEFAULT_CLASS_FIRMWARE_BEGIN + 0x1000) {\r
- return EFI_BROWSER_ACTION_DEFAULT_FIRMWARE + DefaultId - EFI_HII_DEFAULT_CLASS_FIRMWARE_BEGIN;\r
- } else {\r
- return -1;\r
+{\r
+ LIST_ENTRY *Link;\r
+ QUESTION_OPTION *Option;\r
+ INTN Result;\r
+\r
+ Link = GetFirstNode (&Question->OptionListHead);\r
+ while (!IsNull (&Question->OptionListHead, Link)) {\r
+ Option = QUESTION_OPTION_FROM_LINK (Link);\r
+\r
+ if ((CompareHiiValue (&Option->Value, OptionValue, &Result, NULL) == EFI_SUCCESS) && (Result == 0)) {\r
+ //\r
+ // Check the suppressif condition, only a valid option can be return.\r
+ //\r
+ if ((Option->SuppressExpression == NULL) ||\r
+ ((EvaluateExpressionList(Option->SuppressExpression, FALSE, NULL, NULL) == ExpressFalse))) {\r
+ return Option;\r
+ }\r
+ }\r
+\r
+ Link = GetNextNode (&Question->OptionListHead, Link);\r
}\r
+\r
+ return NULL;\r
}\r
\r
+\r
/**\r
Reset Question to its default value.\r
\r
LIST_ENTRY *FormLink;\r
LIST_ENTRY *Link;\r
FORM_BROWSER_STATEMENT *Question;\r
- FORM_BROWSER_FORMSET *BackUpFormSet;\r
FORM_BROWSER_FORMSET *LocalFormSet;\r
- EFI_HII_HANDLE *HiiHandles;\r
- UINTN Index;\r
- EFI_GUID ZeroGuid;\r
\r
Status = EFI_SUCCESS;\r
\r
if ((Question->Storage != NULL) &&\r
(Question->Storage->Type != EFI_HII_VARSTORE_EFI_VARIABLE)) {\r
SetQuestionValue (FormSet, Form, Question, GetSetValueWithEditBuffer);\r
- //\r
- // Update Form NV flag.\r
- //\r
- Form->NvUpdateRequired = TRUE;\r
}\r
}\r
} else if (SettingScope == FormSetLevel) {\r
}\r
} else if (SettingScope == SystemLevel) {\r
//\r
- // Open all FormSet by locate HII packages.\r
- // Initiliaze the maintain FormSet to store default data as back up data.\r
- //\r
- BackUpFormSet = gOldFormSet;\r
- gOldFormSet = NULL;\r
-\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
- //\r
- // Check HiiHandles[Index] does exist in global maintain list. \r
- //\r
- if (GetFormSetFromHiiHandle (HiiHandles[Index]) != NULL) {\r
- continue;\r
- }\r
- \r
- //\r
- // Initilize FormSet Setting\r
- //\r
- LocalFormSet = AllocateZeroPool (sizeof (FORM_BROWSER_FORMSET));\r
- ASSERT (LocalFormSet != NULL);\r
- ZeroMem (&ZeroGuid, sizeof (ZeroGuid));\r
- Status = InitializeFormSet (HiiHandles[Index], &ZeroGuid, LocalFormSet, FALSE);\r
- if (EFI_ERROR (Status) || IsListEmpty (&LocalFormSet->FormListHead)) {\r
- DestroyFormSet (LocalFormSet);\r
- continue;\r
- }\r
- Status = InitializeCurrentSetting (LocalFormSet);\r
- if (EFI_ERROR (Status)) {\r
- DestroyFormSet (LocalFormSet);\r
- continue;\r
- }\r
- //\r
- // Initilize Questions' Value\r
- //\r
- Status = LoadFormSetConfig (NULL, LocalFormSet);\r
- if (EFI_ERROR (Status)) {\r
- DestroyFormSet (LocalFormSet);\r
- continue;\r
- }\r
-\r
- //\r
- // Add FormSet into the maintain list.\r
- //\r
- InsertTailList (&gBrowserFormSetList, &LocalFormSet->Link);\r
- }\r
- \r
- //\r
- // Free resources, and restore gOldFormSet and gClassOfVfr\r
+ // Preload all Hii formset.\r
//\r
- FreePool (HiiHandles);\r
- gOldFormSet = BackUpFormSet;\r
+ LoadAllHiiFormset();\r
\r
//\r
// Set Default Value for each FormSet in the maintain list.\r
return EFI_SUCCESS;\r
}\r
\r
+\r
+/**\r
+ Validate whether this question's value has changed.\r
+\r
+ @param FormSet FormSet data structure.\r
+ @param Form Form data structure.\r
+ @param Question Question to be initialized.\r
+ @param GetValueFrom Where to get value, may from editbuffer, buffer or hii driver.\r
+\r
+ @retval TRUE Question's value has changed.\r
+ @retval FALSE Question's value has not changed\r
+\r
+**/\r
+BOOLEAN\r
+IsQuestionValueChanged (\r
+ IN FORM_BROWSER_FORMSET *FormSet,\r
+ IN FORM_BROWSER_FORM *Form,\r
+ IN OUT FORM_BROWSER_STATEMENT *Question,\r
+ IN GET_SET_QUESTION_VALUE_WITH GetValueFrom\r
+ )\r
+{\r
+ EFI_HII_VALUE BackUpValue;\r
+ CHAR8 *BackUpBuffer;\r
+ EFI_STATUS Status;\r
+ BOOLEAN ValueChanged;\r
+ UINTN BufferWidth;\r
+\r
+ //\r
+ // For quetion without storage, always mark it as data not changed.\r
+ //\r
+ if (Question->Storage == NULL && Question->Operand != EFI_IFR_TIME_OP && Question->Operand != EFI_IFR_DATE_OP) {\r
+ return FALSE;\r
+ }\r
+\r
+ BackUpBuffer = NULL;\r
+ ValueChanged = FALSE;\r
+\r
+ switch (Question->Operand) {\r
+ case EFI_IFR_ORDERED_LIST_OP:\r
+ BufferWidth = Question->StorageWidth;\r
+ BackUpBuffer = AllocateCopyPool (BufferWidth, Question->BufferValue);\r
+ ASSERT (BackUpBuffer != NULL);\r
+ break;\r
+\r
+ case EFI_IFR_STRING_OP:\r
+ case EFI_IFR_PASSWORD_OP:\r
+ BufferWidth = (UINTN) Question->Maximum * sizeof (CHAR16);\r
+ BackUpBuffer = AllocateCopyPool (BufferWidth, Question->BufferValue);\r
+ ASSERT (BackUpBuffer != NULL);\r
+ break;\r
+\r
+ default:\r
+ BufferWidth = 0;\r
+ break;\r
+ }\r
+ CopyMem (&BackUpValue, &Question->HiiValue, sizeof (EFI_HII_VALUE));\r
+\r
+ Status = GetQuestionValue (FormSet, Form, Question, GetValueFrom);\r
+ ASSERT_EFI_ERROR(Status);\r
+\r
+ if (CompareMem (&BackUpValue, &Question->HiiValue, sizeof (EFI_HII_VALUE)) != 0 ||\r
+ CompareMem (BackUpBuffer, Question->BufferValue, BufferWidth) != 0) {\r
+ ValueChanged = TRUE;\r
+ }\r
+\r
+ CopyMem (&Question->HiiValue, &BackUpValue, sizeof (EFI_HII_VALUE));\r
+ CopyMem (Question->BufferValue, BackUpBuffer, BufferWidth);\r
+\r
+ if (BackUpBuffer != NULL) {\r
+ FreePool (BackUpBuffer);\r
+ }\r
+\r
+ return ValueChanged;\r
+}\r
+\r
/**\r
Initialize Question's Edit copy from Storage.\r
\r
//\r
// Initialize local copy of Value for each Question\r
//\r
- Status = GetQuestionValue (FormSet, Form, Question, GetSetValueWithEditBuffer);\r
+ if (Question->Operand == EFI_IFR_PASSWORD_OP && (Question->QuestionFlags & EFI_IFR_FLAG_CALLBACK)== 0) {\r
+ Status = GetQuestionValue (FormSet, Form, Question, GetSetValueWithHiiDriver);\r
+ } else {\r
+ Status = GetQuestionValue (FormSet, Form, Question, GetSetValueWithEditBuffer);\r
+ }\r
if (EFI_ERROR (Status)) {\r
return Status;\r
}\r
Status = ProcessCallBackFunction(Selection, Question, EFI_BROWSER_ACTION_RETRIEVE, TRUE);\r
}\r
\r
+ //\r
+ // Update Question Value changed flag.\r
+ //\r
+ Question->ValueChanged = IsQuestionValueChanged(FormSet, Form, Question, GetSetValueWithBuffer);\r
+\r
Link = GetNextNode (&Form->StatementListHead, Link);\r
}\r
\r
Link = GetNextNode (&FormSet->FormListHead, Link);\r
}\r
\r
+ //\r
+ // Finished question initialization.\r
+ // \r
+ FormSet->QuestionInited = TRUE;\r
+\r
return EFI_SUCCESS;\r
}\r
\r
CHAR16 *NextRequestElement;\r
CHAR16 *SearchKey;\r
\r
+ //\r
+ // No request element in it, just return.\r
+ //\r
+ if (ConfigRequest == NULL) {\r
+ return;\r
+ }\r
+\r
if (Storage->Type == EFI_HII_VARSTORE_NAME_VALUE) {\r
//\r
// "&Name1&Name2" section for EFI_HII_VARSTORE_NAME_VALUE storage\r
{\r
LIST_ENTRY *Link;\r
FORMSET_STORAGE *Storage;\r
+ CHAR16 *ConfigRequest;\r
\r
Link = GetFirstNode (&FormSet->StorageListHead);\r
while (!IsNull (&FormSet->StorageListHead, Link)) {\r
Link = GetNextNode (&FormSet->StorageListHead, Link);\r
\r
if ((Storage->BrowserStorage->Type != EFI_HII_VARSTORE_BUFFER) && \r
- (Storage->BrowserStorage->Type != EFI_HII_VARSTORE_NAME_VALUE)) {\r
+ (Storage->BrowserStorage->Type != EFI_HII_VARSTORE_NAME_VALUE) && \r
+ (Storage->BrowserStorage->Type != EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER)) {\r
continue;\r
}\r
\r
continue;\r
}\r
\r
- RemoveConfigRequest (Storage->BrowserStorage, Storage->ConfigRequest);\r
+ ConfigRequest = FormSet->QuestionInited ? Storage->ConfigRequest : Storage->ConfigElements;\r
+ RemoveConfigRequest (Storage->BrowserStorage, ConfigRequest);\r
}\r
}\r
\r
Adjust the config request info, remove the request elements which already in AllConfigRequest string.\r
\r
@param Storage Form set Storage.\r
- @param ConfigRequest Return the ConfigRequest info.\r
\r
@retval TRUE Has element not covered by current used elements, need to continue to call ExtractConfig\r
@retval FALSE All elements covered by current used elements.\r
**/\r
BOOLEAN \r
ConfigRequestAdjust (\r
- IN FORMSET_STORAGE *Storage,\r
- OUT CHAR16 **ConfigRequest\r
+ IN FORMSET_STORAGE *Storage\r
)\r
{\r
CHAR16 *RequestElement;\r
\r
if (Storage->BrowserStorage->ConfigRequest == NULL) {\r
Storage->BrowserStorage->ConfigRequest = AllocateCopyPool (StrSize (Storage->ConfigRequest), Storage->ConfigRequest);\r
- *ConfigRequest = AllocateCopyPool (StrSize (Storage->ConfigRequest), Storage->ConfigRequest);\r
+ if (Storage->ConfigElements != NULL) {\r
+ FreePool (Storage->ConfigElements);\r
+ }\r
+ Storage->ConfigElements = AllocateCopyPool (StrSize (Storage->ConfigRequest), Storage->ConfigRequest);\r
return TRUE;\r
}\r
\r
}\r
\r
if (RetVal) {\r
- *ConfigRequest = RetBuf;\r
+ if (Storage->ConfigElements != NULL) {\r
+ FreePool (Storage->ConfigElements);\r
+ }\r
+ Storage->ConfigElements = RetBuf;\r
} else {\r
FreePool (RetBuf);\r
}\r
return RetVal;\r
}\r
\r
+/**\r
+\r
+ Base on ConfigRequest info to get default value for current formset. \r
+\r
+ ConfigRequest info include the info about which questions in current formset need to \r
+ get default value. This function only get these questions default value.\r
+ \r
+ @param FormSet FormSet data structure.\r
+ @param Storage Storage need to update value.\r
+ @param ConfigRequest The config request string.\r
+\r
+**/\r
+VOID\r
+GetDefaultForFormset (\r
+ IN FORM_BROWSER_FORMSET *FormSet,\r
+ IN BROWSER_STORAGE *Storage,\r
+ IN CHAR16 *ConfigRequest\r
+ )\r
+{\r
+ UINT8 *BackUpBuf;\r
+ UINTN BufferSize;\r
+ LIST_ENTRY BackUpList;\r
+ NAME_VALUE_NODE *Node;\r
+ LIST_ENTRY *Link;\r
+ LIST_ENTRY *NodeLink;\r
+ NAME_VALUE_NODE *TmpNode;\r
+ EFI_STATUS Status;\r
+ EFI_STRING Progress;\r
+ EFI_STRING Result;\r
+\r
+ BackUpBuf = NULL;\r
+ InitializeListHead(&BackUpList);\r
+\r
+ //\r
+ // Back update the edit buffer.\r
+ // \r
+ if (Storage->Type == EFI_HII_VARSTORE_BUFFER || \r
+ (Storage->Type == EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER)) {\r
+ BackUpBuf = AllocateCopyPool (Storage->Size, Storage->EditBuffer);\r
+ ASSERT (BackUpBuf != NULL);\r
+ } else if (Storage->Type == EFI_HII_VARSTORE_NAME_VALUE) {\r
+ Link = GetFirstNode (&Storage->NameValueListHead);\r
+ while (!IsNull (&Storage->NameValueListHead, Link)) {\r
+ Node = NAME_VALUE_NODE_FROM_LINK (Link);\r
+ Link = GetNextNode (&Storage->NameValueListHead, Link);\r
+\r
+ //\r
+ // Only back Node belong to this formset.\r
+ //\r
+ if (StrStr (Storage->ConfigRequest, Node->Name) == NULL) {\r
+ continue;\r
+ }\r
+\r
+ TmpNode = AllocateCopyPool (sizeof (NAME_VALUE_NODE), Node);\r
+ TmpNode->Name = AllocateCopyPool (StrSize(Node->Name) * sizeof (CHAR16), Node->Name);\r
+ TmpNode->EditValue = AllocateCopyPool (StrSize(Node->EditValue) * sizeof (CHAR16), Node->EditValue);\r
+\r
+ InsertTailList(&BackUpList, &TmpNode->Link);\r
+ }\r
+ }\r
+\r
+ //\r
+ // Get default value.\r
+ //\r
+ ExtractDefault (FormSet, NULL, EFI_HII_DEFAULT_CLASS_STANDARD, FormSetLevel, GetDefaultForStorage, Storage, TRUE);\r
+\r
+ //\r
+ // Update the question value based on the input ConfigRequest.\r
+ //\r
+ if (Storage->Type == EFI_HII_VARSTORE_BUFFER || \r
+ (Storage->Type == EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER)) {\r
+ ASSERT (BackUpBuf != NULL);\r
+ BufferSize = Storage->Size;\r
+ Status = mHiiConfigRouting->BlockToConfig(\r
+ mHiiConfigRouting,\r
+ ConfigRequest,\r
+ Storage->EditBuffer,\r
+ BufferSize,\r
+ &Result,\r
+ &Progress\r
+ );\r
+ ASSERT_EFI_ERROR (Status);\r
+ \r
+ Status = mHiiConfigRouting->ConfigToBlock (\r
+ mHiiConfigRouting,\r
+ Result,\r
+ BackUpBuf,\r
+ &BufferSize,\r
+ &Progress\r
+ );\r
+ ASSERT_EFI_ERROR (Status);\r
+\r
+ if (Result != NULL) {\r
+ FreePool (Result);\r
+ }\r
+ \r
+ CopyMem (Storage->EditBuffer, BackUpBuf, Storage->Size);\r
+ FreePool (BackUpBuf);\r
+ } else if (Storage->Type == EFI_HII_VARSTORE_NAME_VALUE) {\r
+ //\r
+ // Update question value, only element in ConfigReqeust will be update.\r
+ //\r
+ Link = GetFirstNode (&BackUpList);\r
+ while (!IsNull (&BackUpList, Link)) {\r
+ Node = NAME_VALUE_NODE_FROM_LINK (Link);\r
+ Link = GetNextNode (&BackUpList, Link);\r
+\r
+ if (StrStr (ConfigRequest, Node->Name) != NULL) {\r
+ continue;\r
+ }\r
+\r
+ NodeLink = GetFirstNode (&Storage->NameValueListHead);\r
+ while (!IsNull (&Storage->NameValueListHead, NodeLink)) {\r
+ TmpNode = NAME_VALUE_NODE_FROM_LINK (NodeLink);\r
+ NodeLink = GetNextNode (&Storage->NameValueListHead, NodeLink);\r
+ \r
+ if (StrCmp (Node->Name, TmpNode->Name) != 0) {\r
+ continue;\r
+ }\r
+\r
+ FreePool (TmpNode->EditValue);\r
+ TmpNode->EditValue = AllocateCopyPool (StrSize(Node->EditValue) * sizeof (CHAR16), Node->EditValue);\r
+\r
+ RemoveEntryList (&Node->Link);\r
+ FreePool (Node->EditValue);\r
+ FreePool (Node->Name);\r
+ FreePool (Node);\r
+ }\r
+ }\r
+\r
+ //\r
+ // Restore the Name/Value node.\r
+ // \r
+ Link = GetFirstNode (&BackUpList);\r
+ while (!IsNull (&BackUpList, Link)) {\r
+ Node = NAME_VALUE_NODE_FROM_LINK (Link);\r
+ Link = GetNextNode (&BackUpList, Link);\r
+ \r
+ //\r
+ // Free this node.\r
+ //\r
+ RemoveEntryList (&Node->Link);\r
+ FreePool (Node->EditValue);\r
+ FreePool (Node->Name);\r
+ FreePool (Node);\r
+ }\r
+ }\r
+}\r
+\r
/**\r
Fill storage's edit copy with settings requested from Configuration Driver.\r
\r
@param FormSet FormSet data structure.\r
@param Storage Buffer Storage.\r
\r
- @retval EFI_SUCCESS The function completed successfully.\r
-\r
**/\r
-EFI_STATUS\r
+VOID\r
LoadStorage (\r
IN FORM_BROWSER_FORMSET *FormSet,\r
IN FORMSET_STORAGE *Storage\r
EFI_STRING Progress;\r
EFI_STRING Result;\r
CHAR16 *StrPtr;\r
- CHAR16 *ConfigRequest;\r
\r
- if (Storage->BrowserStorage->Type == EFI_HII_VARSTORE_EFI_VARIABLE) {\r
- return EFI_SUCCESS;\r
- }\r
+ switch (Storage->BrowserStorage->Type) {\r
+ case EFI_HII_VARSTORE_EFI_VARIABLE:\r
+ return;\r
+\r
+ case EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER:\r
+ if (Storage->BrowserStorage->ReferenceCount > 1) {\r
+ ConfigRequestAdjust(Storage);\r
+ return;\r
+ }\r
\r
- if (Storage->BrowserStorage->Type == EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER) {\r
- Status = EFI_SUCCESS;\r
- //\r
- // EFI varstore data all get from variable, so no need to get again.\r
- //\r
- if (Storage->BrowserStorage->ReferenceCount == 1) {\r
Status = gRT->GetVariable (\r
Storage->BrowserStorage->Name,\r
&Storage->BrowserStorage->Guid,\r
(UINTN*)&Storage->BrowserStorage->Size,\r
Storage->BrowserStorage->EditBuffer\r
);\r
- }\r
- return Status;\r
- }\r
+ //\r
+ // If get variable fail, extract default from IFR binary\r
+ //\r
+ if (EFI_ERROR (Status)) {\r
+ ExtractDefault (FormSet, NULL, EFI_HII_DEFAULT_CLASS_STANDARD, FormSetLevel, GetDefaultForStorage, Storage->BrowserStorage, TRUE);\r
+ }\r
+\r
+ Storage->BrowserStorage->ConfigRequest = AllocateCopyPool (StrSize (Storage->ConfigRequest), Storage->ConfigRequest);\r
+ //\r
+ // Input NULL for ConfigRequest field means sync all fields from editbuffer to buffer. \r
+ //\r
+ SynchronizeStorage(FormSet, Storage->BrowserStorage, NULL, TRUE);\r
+ break;\r
\r
- if (FormSet->ConfigAccess == NULL) {\r
- return EFI_NOT_FOUND;\r
- }\r
+ case EFI_HII_VARSTORE_BUFFER:\r
+ case EFI_HII_VARSTORE_NAME_VALUE:\r
+ //\r
+ // Skip if there is no RequestElement\r
+ //\r
+ if (Storage->ElementCount == 0) {\r
+ return;\r
+ }\r
\r
- if (Storage->ElementCount == 0) {\r
- //\r
- // Skip if there is no RequestElement\r
- //\r
- return EFI_SUCCESS;\r
- }\r
+ //\r
+ // Adjust the ConfigRequest string, only the field not saved in BrowserStorage->AllConfig\r
+ // will used to call ExtractConfig.\r
+ // If not elements need to udpate, return.\r
+ //\r
+ if (!ConfigRequestAdjust(Storage)) {\r
+ return;\r
+ }\r
+ ASSERT (Storage->ConfigElements != NULL);\r
\r
- //\r
- // Adjust the ConfigRequest string, only the field not saved in BrowserStorage->AllConfig\r
- // will used to call ExtractConfig.\r
- //\r
- if (!ConfigRequestAdjust(Storage, &ConfigRequest)) {\r
- return EFI_SUCCESS;\r
- }\r
+ Status = EFI_NOT_FOUND;\r
+ if (FormSet->ConfigAccess != NULL) { \r
+ //\r
+ // Request current settings from Configuration Driver\r
+ //\r
+ Status = FormSet->ConfigAccess->ExtractConfig (\r
+ FormSet->ConfigAccess,\r
+ Storage->ConfigElements,\r
+ &Progress,\r
+ &Result\r
+ );\r
+ \r
+ if (!EFI_ERROR (Status)) {\r
+ //\r
+ // Convert Result from <ConfigAltResp> to <ConfigResp>\r
+ //\r
+ StrPtr = StrStr (Result, L"&GUID=");\r
+ if (StrPtr != NULL) {\r
+ *StrPtr = L'\0';\r
+ }\r
+ \r
+ Status = ConfigRespToStorage (Storage->BrowserStorage, Result);\r
+ FreePool (Result);\r
+ }\r
+ }\r
\r
- //\r
- // Request current settings from Configuration Driver\r
- //\r
- Status = FormSet->ConfigAccess->ExtractConfig (\r
- FormSet->ConfigAccess,\r
- ConfigRequest,\r
- &Progress,\r
- &Result\r
- );\r
- FreePool (ConfigRequest);\r
+ if (EFI_ERROR (Status)) {\r
+ //\r
+ // Base on the configRequest string to get default value.\r
+ //\r
+ GetDefaultForFormset (FormSet, Storage->BrowserStorage, Storage->ConfigElements);\r
+ }\r
\r
- if (EFI_ERROR (Status)) {\r
- return Status;\r
- }\r
+ SynchronizeStorage(FormSet, Storage->BrowserStorage, Storage->ConfigElements, TRUE);\r
+ break;\r
\r
- //\r
- // Convert Result from <ConfigAltResp> to <ConfigResp>\r
- //\r
- StrPtr = StrStr (Result, L"&GUID=");\r
- if (StrPtr != NULL) {\r
- *StrPtr = L'\0';\r
+ default:\r
+ break;\r
}\r
-\r
- Status = ConfigRespToStorage (Storage->BrowserStorage, Result);\r
- FreePool (Result);\r
- return Status;\r
}\r
\r
/**\r
\r
@param FormSet FormSet data structure.\r
\r
- @retval EFI_SUCCESS The function completed successfully.\r
-\r
**/\r
-EFI_STATUS\r
+VOID\r
InitializeCurrentSetting (\r
IN OUT FORM_BROWSER_FORMSET *FormSet\r
)\r
{\r
LIST_ENTRY *Link;\r
- LIST_ENTRY *Link2;\r
FORMSET_STORAGE *Storage;\r
- FORMSET_STORAGE *StorageSrc;\r
- FORMSET_STORAGE *OldStorage;\r
- FORM_BROWSER_FORM *Form;\r
- FORM_BROWSER_FORM *Form2;\r
- EFI_STATUS Status;\r
+ FORM_BROWSER_FORMSET *OldFormSet;\r
\r
//\r
// Extract default from IFR binary for no storage questions.\r
while (!IsNull (&FormSet->StorageListHead, Link)) {\r
Storage = FORMSET_STORAGE_FROM_LINK (Link);\r
\r
- OldStorage = NULL;\r
- if (gOldFormSet != NULL) {\r
- //\r
- // Try to find the Storage in backup formset gOldFormSet\r
- //\r
- Link2 = GetFirstNode (&gOldFormSet->StorageListHead);\r
- while (!IsNull (&gOldFormSet->StorageListHead, Link2)) {\r
- StorageSrc = FORMSET_STORAGE_FROM_LINK (Link2);\r
-\r
- if (StorageSrc->VarStoreId == Storage->VarStoreId) {\r
- OldStorage = StorageSrc;\r
- break;\r
- }\r
-\r
- Link2 = GetNextNode (&gOldFormSet->StorageListHead, Link2);\r
- }\r
- }\r
-\r
- //\r
- // Storage is not found in backup formset and current global storage not has other driver used,\r
- // request it from ConfigDriver\r
- //\r
- if (OldStorage == NULL) {\r
- Status = LoadStorage (FormSet, Storage);\r
-\r
- if (EFI_ERROR (Status)) {\r
- //\r
- // If get last time changed value failed, extract default from IFR binary\r
- //\r
- ExtractDefault (FormSet, NULL, EFI_HII_DEFAULT_CLASS_STANDARD, FormSetLevel, GetDefaultForStorage, Storage->BrowserStorage, TRUE);\r
- //\r
- // ExtractDefault will set the NV flag to TRUE, so need this function to clean the flag\r
- // in current situation.\r
- //\r
- UpdateNvInfoInForm (FormSet, FALSE);\r
- }\r
-\r
- //\r
- // Now Edit Buffer is filled with default values(lower priority) or current\r
- // settings(higher priority), sychronize it to shadow Buffer\r
- //\r
- SynchronizeStorage (Storage->BrowserStorage, TRUE);\r
- }\r
+ LoadStorage (FormSet, Storage);\r
\r
Link = GetNextNode (&FormSet->StorageListHead, Link);\r
}\r
\r
//\r
- // If has old formset, get the old nv update status.\r
+ // Try to find pre FormSet in the maintain backup list.\r
+ // If old formset != NULL, destroy this formset. Add new formset to gBrowserFormSetList.\r
//\r
- if (gOldFormSet != NULL) {\r
- Link = GetFirstNode (&FormSet->FormListHead);\r
- while (!IsNull (&FormSet->FormListHead, Link)) {\r
- Form = FORM_BROWSER_FORM_FROM_LINK (Link);\r
-\r
- Link2 = GetFirstNode (&gOldFormSet->FormListHead);\r
- while (!IsNull (&gOldFormSet->FormListHead, Link2)) {\r
- Form2 = FORM_BROWSER_FORM_FROM_LINK (Link2);\r
-\r
- if (Form->FormId == Form2->FormId) {\r
- Form->NvUpdateRequired = Form2->NvUpdateRequired;\r
- break;\r
- }\r
-\r
- Link2 = GetNextNode (&gOldFormSet->FormListHead, Link2);\r
- }\r
- Link = GetNextNode (&FormSet->FormListHead, Link);\r
- }\r
+ OldFormSet = GetFormSetFromHiiHandle (FormSet->HiiHandle);\r
+ if (OldFormSet != NULL) {\r
+ RemoveEntryList (&OldFormSet->Link);\r
+ DestroyFormSet (OldFormSet);\r
}\r
-\r
- return EFI_SUCCESS;\r
+ InsertTailList (&gBrowserFormSetList, &FormSet->Link);\r
}\r
\r
\r
found in package list.\r
On output, GUID of the formset found(if not NULL).\r
@param FormSet FormSet data structure.\r
- @param UpdateGlobalVar Whether need to update the global variable.\r
\r
@retval EFI_SUCCESS The function completed successfully.\r
@retval EFI_NOT_FOUND The specified FormSet could not be found.\r
InitializeFormSet (\r
IN EFI_HII_HANDLE Handle,\r
IN OUT EFI_GUID *FormSetGuid,\r
- OUT FORM_BROWSER_FORMSET *FormSet,\r
- IN BOOLEAN UpdateGlobalVar \r
+ OUT FORM_BROWSER_FORMSET *FormSet\r
)\r
{\r
EFI_STATUS Status;\r
EFI_HANDLE DriverHandle;\r
- UINT16 Index;\r
\r
Status = GetIfrBinaryData (Handle, FormSetGuid, &FormSet->IfrBinaryLength, &FormSet->IfrBinaryData);\r
if (EFI_ERROR (Status)) {\r
FormSet->Signature = FORM_BROWSER_FORMSET_SIGNATURE;\r
FormSet->HiiHandle = Handle;\r
CopyMem (&FormSet->Guid, FormSetGuid, sizeof (EFI_GUID));\r
+ FormSet->QuestionInited = FALSE;\r
\r
//\r
// Retrieve ConfigAccess Protocol associated with this HiiPackageList\r
// Parse the IFR binary OpCodes\r
//\r
Status = ParseOpCodes (FormSet);\r
- if (EFI_ERROR (Status)) {\r
- return Status;\r
- }\r
\r
- // \r
- // If not need to update the global variable, just return.\r
- //\r
- if (!UpdateGlobalVar) {\r
- return Status;\r
- }\r
-\r
- //\r
- // Set VFR type by FormSet SubClass field\r
- //\r
- gClassOfVfr = FORMSET_CLASS_PLATFORM_SETUP;\r
- if (FormSet->SubClass == EFI_FRONT_PAGE_SUBCLASS) {\r
- gClassOfVfr = FORMSET_CLASS_FRONT_PAGE;\r
- }\r
- \r
- //\r
- // Set VFR type by FormSet class guid\r
- //\r
- for (Index = 0; Index < 3; Index ++) {\r
- if (CompareGuid (&FormSet->ClassGuid[Index], &gEfiHiiPlatformSetupFormsetGuid)) {\r
- gClassOfVfr |= FORMSET_CLASS_PLATFORM_SETUP;\r
- break;\r
- }\r
- }\r
-\r
- gFunctionKeySetting = ENABLE_FUNCTION_KEY_SETTING;\r
-\r
- if ((gClassOfVfr & FORMSET_CLASS_FRONT_PAGE) == FORMSET_CLASS_FRONT_PAGE) {\r
- gFrontPageHandle = FormSet->HiiHandle;\r
- gFunctionKeySetting = NONE_FUNCTION_KEY_SETTING;\r
- }\r
-\r
- //\r
- // Match GUID to find out the function key setting. If match fail, use the default setting.\r
- //\r
- for (Index = 0; Index < sizeof (gFunctionKeySettingTable) / sizeof (FUNCTIION_KEY_SETTING); Index++) {\r
- if (CompareGuid (&FormSet->Guid, &(gFunctionKeySettingTable[Index].FormSetGuid))) {\r
- //\r
- // Update the function key setting.\r
- //\r
- gFunctionKeySetting = gFunctionKeySettingTable[Index].KeySetting;\r
- }\r
- }\r
-\r
- return EFI_SUCCESS;\r
+ return Status;\r
}\r
\r
\r
)\r
{\r
BROWSER_CONTEXT *Context;\r
+ FORM_ENTRY_INFO *MenuList;\r
\r
gBrowserContextCount++;\r
if (gBrowserContextCount == 1) {\r
//\r
// Save FormBrowser context\r
//\r
- Context->BannerData = gBannerData;\r
- Context->ClassOfVfr = gClassOfVfr;\r
- Context->FunctionKeySetting = gFunctionKeySetting;\r
+ Context->Selection = gCurrentSelection;\r
Context->ResetRequired = gResetRequired;\r
- Context->Direction = gDirection;\r
- Context->EnterString = gEnterString;\r
- Context->EnterCommitString = gEnterCommitString;\r
- Context->EnterEscapeString = gEnterEscapeString;\r
- Context->EscapeString = gEscapeString;\r
- Context->MoveHighlight = gMoveHighlight;\r
- Context->MakeSelection = gMakeSelection;\r
- Context->DecNumericInput = gDecNumericInput;\r
- Context->HexNumericInput = gHexNumericInput;\r
- Context->ToggleCheckBox = gToggleCheckBox;\r
- Context->PromptForData = gPromptForData;\r
- Context->PromptForPassword = gPromptForPassword;\r
- Context->PromptForNewPassword = gPromptForNewPassword;\r
- Context->ConfirmPassword = gConfirmPassword;\r
- Context->ConfirmError = gConfirmError;\r
- Context->PassowordInvalid = gPassowordInvalid;\r
- Context->PressEnter = gPressEnter;\r
- Context->EmptyString = gEmptyString;\r
- Context->AreYouSure = gAreYouSure;\r
- Context->YesResponse = gYesResponse;\r
- Context->NoResponse = gNoResponse;\r
- Context->MiniString = gMiniString;\r
- Context->PlusString = gPlusString;\r
- Context->MinusString = gMinusString;\r
- Context->AdjustNumber = gAdjustNumber;\r
- Context->SaveChanges = gSaveChanges;\r
- Context->OptionMismatch = gOptionMismatch;\r
- Context->FormSuppress = gFormSuppress;\r
- Context->PromptBlockWidth = gPromptBlockWidth;\r
- Context->OptionBlockWidth = gOptionBlockWidth;\r
- Context->HelpBlockWidth = gHelpBlockWidth;\r
- Context->OldFormSet = gOldFormSet;\r
- Context->MenuRefreshHead = gMenuRefreshHead;\r
- Context->ProtocolNotFound = gProtocolNotFound;\r
-\r
- CopyMem (&Context->ScreenDimensions, &gScreenDimensions, sizeof (gScreenDimensions));\r
- CopyMem (&Context->MenuOption, &gMenuOption, sizeof (gMenuOption));\r
+ Context->ExitRequired = gExitRequired;\r
+ Context->HiiHandle = mCurrentHiiHandle;\r
+ Context->FormId = mCurrentFormId;\r
+ CopyGuid (&Context->FormSetGuid, &mCurrentFormSetGuid);\r
+\r
+ //\r
+ // Save the menu history data.\r
+ //\r
+ InitializeListHead(&Context->FormHistoryList);\r
+ while (!IsListEmpty (&mPrivateData.FormBrowserEx2.FormViewHistoryHead)) {\r
+ MenuList = FORM_ENTRY_INFO_FROM_LINK (mPrivateData.FormBrowserEx2.FormViewHistoryHead.ForwardLink);\r
+ RemoveEntryList (&MenuList->Link);\r
+\r
+ InsertTailList(&Context->FormHistoryList, &MenuList->Link);\r
+ }\r
\r
//\r
// Insert to FormBrowser context list\r
{\r
LIST_ENTRY *Link;\r
BROWSER_CONTEXT *Context;\r
+ FORM_ENTRY_INFO *MenuList;\r
\r
ASSERT (gBrowserContextCount != 0);\r
gBrowserContextCount--;\r
//\r
// Restore FormBrowser context\r
//\r
- gBannerData = Context->BannerData;\r
- gClassOfVfr = Context->ClassOfVfr;\r
- gFunctionKeySetting = Context->FunctionKeySetting;\r
+ gCurrentSelection = Context->Selection;\r
gResetRequired = Context->ResetRequired;\r
- gDirection = Context->Direction;\r
- gEnterString = Context->EnterString;\r
- gEnterCommitString = Context->EnterCommitString;\r
- gEnterEscapeString = Context->EnterEscapeString;\r
- gEscapeString = Context->EscapeString;\r
- gMoveHighlight = Context->MoveHighlight;\r
- gMakeSelection = Context->MakeSelection;\r
- gDecNumericInput = Context->DecNumericInput;\r
- gHexNumericInput = Context->HexNumericInput;\r
- gToggleCheckBox = Context->ToggleCheckBox;\r
- gPromptForData = Context->PromptForData;\r
- gPromptForPassword = Context->PromptForPassword;\r
- gPromptForNewPassword = Context->PromptForNewPassword;\r
- gConfirmPassword = Context->ConfirmPassword;\r
- gConfirmError = Context->ConfirmError;\r
- gPassowordInvalid = Context->PassowordInvalid;\r
- gPressEnter = Context->PressEnter;\r
- gEmptyString = Context->EmptyString;\r
- gAreYouSure = Context->AreYouSure;\r
- gYesResponse = Context->YesResponse;\r
- gNoResponse = Context->NoResponse;\r
- gMiniString = Context->MiniString;\r
- gPlusString = Context->PlusString;\r
- gMinusString = Context->MinusString;\r
- gAdjustNumber = Context->AdjustNumber;\r
- gSaveChanges = Context->SaveChanges;\r
- gOptionMismatch = Context->OptionMismatch;\r
- gFormSuppress = Context->FormSuppress;\r
- gPromptBlockWidth = Context->PromptBlockWidth;\r
- gOptionBlockWidth = Context->OptionBlockWidth;\r
- gHelpBlockWidth = Context->HelpBlockWidth;\r
- gOldFormSet = Context->OldFormSet;\r
- gMenuRefreshHead = Context->MenuRefreshHead;\r
- gProtocolNotFound = Context->ProtocolNotFound;\r
-\r
- CopyMem (&gScreenDimensions, &Context->ScreenDimensions, sizeof (gScreenDimensions));\r
- CopyMem (&gMenuOption, &Context->MenuOption, sizeof (gMenuOption));\r
+ gExitRequired = Context->ExitRequired;\r
+ mCurrentHiiHandle = Context->HiiHandle;\r
+ mCurrentFormId = Context->FormId;\r
+ CopyGuid (&mCurrentFormSetGuid, &Context->FormSetGuid);\r
+\r
+ //\r
+ // Restore the menu history data.\r
+ //\r
+ while (!IsListEmpty (&Context->FormHistoryList)) {\r
+ MenuList = FORM_ENTRY_INFO_FROM_LINK (Context->FormHistoryList.ForwardLink);\r
+ RemoveEntryList (&MenuList->Link);\r
+\r
+ InsertTailList(&mPrivateData.FormBrowserEx2.FormViewHistoryHead, &MenuList->Link);\r
+ }\r
\r
//\r
// Remove from FormBrowser context list\r
//\r
// HiiHandle is Current FormSet.\r
//\r
- if ((gOldFormSet != NULL) && (gOldFormSet->HiiHandle == Handle)) {\r
+ if (mCurrentHiiHandle == Handle) {\r
return TRUE;\r
}\r
\r
Link = GetFirstNode (&gBrowserContextList);\r
while (!IsNull (&gBrowserContextList, Link)) {\r
Context = BROWSER_CONTEXT_FROM_LINK (Link);\r
- if (Context->OldFormSet->HiiHandle == Handle) {\r
+ if (Context->HiiHandle == Handle) {\r
//\r
// HiiHandle is in BrowserContext\r
//\r
return FALSE;\r
}\r
\r
+/**\r
+ Perform Password check. \r
+ Passwork may be encrypted by driver that requires the specific check.\r
+ \r
+ @param Form Form where Password Statement is in.\r
+ @param Statement Password statement\r
+ @param PasswordString Password string to be checked. It may be NULL.\r
+ NULL means to restore password.\r
+ "" string can be used to checked whether old password does exist.\r
+ \r
+ @return Status Status of Password check.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+PasswordCheck (\r
+ IN FORM_DISPLAY_ENGINE_FORM *Form,\r
+ IN FORM_DISPLAY_ENGINE_STATEMENT *Statement,\r
+ IN EFI_STRING PasswordString OPTIONAL\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ EFI_HII_CONFIG_ACCESS_PROTOCOL *ConfigAccess;\r
+ EFI_BROWSER_ACTION_REQUEST ActionRequest;\r
+ EFI_IFR_TYPE_VALUE IfrTypeValue;\r
+ FORM_BROWSER_STATEMENT *Question;\r
+\r
+ ConfigAccess = gCurrentSelection->FormSet->ConfigAccess;\r
+ Question = GetBrowserStatement(Statement);\r
+ ASSERT (Question != NULL);\r
+\r
+ if ((Question->QuestionFlags & EFI_IFR_FLAG_CALLBACK) == EFI_IFR_FLAG_CALLBACK) {\r
+ if (ConfigAccess == NULL) {\r
+ return EFI_UNSUPPORTED;\r
+ }\r
+ } else {\r
+ if (PasswordString == NULL) {\r
+ return EFI_SUCCESS;\r
+ } \r
+ \r
+ if (StrnCmp (PasswordString, (CHAR16 *) Question->BufferValue, Question->StorageWidth/sizeof (CHAR16)) == 0) {\r
+ return EFI_SUCCESS;\r
+ } else {\r
+ return EFI_NOT_READY;\r
+ }\r
+ }\r
+ \r
+ //\r
+ // Prepare password string in HII database\r
+ //\r
+ if (PasswordString != NULL) {\r
+ IfrTypeValue.string = NewString (PasswordString, gCurrentSelection->FormSet->HiiHandle);\r
+ } else {\r
+ IfrTypeValue.string = 0;\r
+ }\r
+\r
+ //\r
+ // Send password to Configuration Driver for validation\r
+ //\r
+ Status = ConfigAccess->Callback (\r
+ ConfigAccess,\r
+ EFI_BROWSER_ACTION_CHANGING,\r
+ Question->QuestionId,\r
+ Question->HiiValue.Type,\r
+ &IfrTypeValue,\r
+ &ActionRequest\r
+ );\r
+\r
+ //\r
+ // Remove password string from HII database\r
+ //\r
+ if (PasswordString != NULL) {\r
+ DeleteString (IfrTypeValue.string, gCurrentSelection->FormSet->HiiHandle);\r
+ }\r
+\r
+ return Status;\r
+}\r
+\r
/**\r
Find the registered HotKey based on KeyData.\r
\r
if (Scope >= MaxLevel) {\r
return EFI_INVALID_PARAMETER;\r
}\r
- \r
+\r
//\r
// When no hot key registered in system or on the first setting,\r
// Scope can be set.\r
return;\r
}\r
\r
+/**\r
+ Check whether the browser data has been modified.\r
+\r
+ @retval TRUE Browser data is modified.\r
+ @retval FALSE No browser data is modified.\r
+\r
+**/\r
+BOOLEAN\r
+EFIAPI\r
+IsBrowserDataModified (\r
+ VOID\r
+ )\r
+{\r
+ LIST_ENTRY *Link;\r
+ FORM_BROWSER_FORMSET *FormSet;\r
+\r
+ if (gCurrentSelection == NULL) {\r
+ return FALSE;\r
+ }\r
+\r
+ switch (gBrowserSettingScope) {\r
+ case FormLevel:\r
+ return IsNvUpdateRequiredForForm (gCurrentSelection->Form);\r
+\r
+ case FormSetLevel:\r
+ return IsNvUpdateRequiredForFormSet (gCurrentSelection->FormSet);\r
+\r
+ case SystemLevel:\r
+ Link = GetFirstNode (&gBrowserFormSetList);\r
+ while (!IsNull (&gBrowserFormSetList, Link)) {\r
+ FormSet = FORM_BROWSER_FORMSET_FROM_LINK (Link);\r
+ if (IsNvUpdateRequiredForFormSet (FormSet)) {\r
+ return TRUE;\r
+ }\r
+ Link = GetNextNode (&gBrowserFormSetList, Link);\r
+ }\r
+ return FALSE;\r
+\r
+ default:\r
+ return FALSE;\r
+ }\r
+}\r
+\r
+/**\r
+ Execute the action requested by the Action parameter.\r
+\r
+ @param[in] Action Execute the request action.\r
+ @param[in] DefaultId The default Id info when need to load default value. Only used when Action is BROWSER_ACTION_DEFAULT.\r
+\r
+ @retval EFI_SUCCESS Execute the request action succss.\r
+ @retval EFI_INVALID_PARAMETER The input action value is invalid.\r
+\r
+**/\r
+EFI_STATUS \r
+EFIAPI\r
+ExecuteAction (\r
+ IN UINT32 Action,\r
+ IN UINT16 DefaultId\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+\r
+ if (gCurrentSelection == NULL) {\r
+ return EFI_NOT_READY;\r
+ }\r
+\r
+ Status = EFI_SUCCESS;\r
+\r
+ //\r
+ // Executet the discard action.\r
+ //\r
+ if ((Action & BROWSER_ACTION_DISCARD) != 0) {\r
+ Status = DiscardForm (gCurrentSelection->FormSet, gCurrentSelection->Form, gBrowserSettingScope);\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+ }\r
+\r
+ //\r
+ // Executet the difault action.\r
+ //\r
+ if ((Action & BROWSER_ACTION_DEFAULT) != 0) {\r
+ Status = ExtractDefault (gCurrentSelection->FormSet, gCurrentSelection->Form, DefaultId, gBrowserSettingScope, GetDefaultForAll, NULL, FALSE);\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+ }\r
+\r
+ //\r
+ // Executet the submit action.\r
+ //\r
+ if ((Action & BROWSER_ACTION_SUBMIT) != 0) {\r
+ Status = SubmitForm (gCurrentSelection->FormSet, gCurrentSelection->Form, gBrowserSettingScope);\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+ }\r
+\r
+ //\r
+ // Executet the reset action.\r
+ //\r
+ if ((Action & BROWSER_ACTION_RESET) != 0) {\r
+ gResetRequired = TRUE;\r
+ }\r
+\r
+ //\r
+ // Executet the exit action.\r
+ //\r
+ if ((Action & BROWSER_ACTION_EXIT) != 0) {\r
+ DiscardForm (gCurrentSelection->FormSet, gCurrentSelection->Form, gBrowserSettingScope);\r
+ if (gBrowserSettingScope == SystemLevel) {\r
+ if (ExitHandlerFunction != NULL) {\r
+ ExitHandlerFunction ();\r
+ }\r
+ }\r
+\r
+ gExitRequired = TRUE;\r
+ }\r
+\r
+ return Status;\r
+}\r
+\r
/**\r
Create reminder to let user to choose save or discard the changed browser data.\r
Caller can use it to actively check the changed browser data.\r
FORM_BROWSER_FORMSET *FormSet;\r
BOOLEAN IsDataChanged;\r
UINT32 DataSavedAction;\r
- CHAR16 *YesResponse;\r
- CHAR16 *NoResponse;\r
- CHAR16 *EmptyString;\r
- CHAR16 *ChangeReminderString;\r
- CHAR16 *SaveConfirmString;\r
- EFI_INPUT_KEY Key;\r
\r
DataSavedAction = BROWSER_NO_CHANGES;\r
IsDataChanged = FALSE;\r
if (!ValidateFormSet(FormSet)) {\r
continue;\r
}\r
- if (IsNvUpdateRequired (FormSet)) {\r
+ if (IsNvUpdateRequiredForFormSet (FormSet)) {\r
IsDataChanged = TRUE;\r
break;\r
}\r
}\r
\r
//\r
- // If data is changed, prompt user\r
+ // If data is changed, prompt user to save or discard it. \r
//\r
- gST->ConIn->ReadKeyStroke (gST->ConIn, &Key);\r
-\r
- YesResponse = GetToken (STRING_TOKEN (ARE_YOU_SURE_YES), gHiiHandle);\r
- ASSERT (YesResponse != NULL);\r
- NoResponse = GetToken (STRING_TOKEN (ARE_YOU_SURE_NO), gHiiHandle);\r
- ASSERT (NoResponse != NULL);\r
- EmptyString = GetToken (STRING_TOKEN (EMPTY_STRING), gHiiHandle);\r
- ChangeReminderString = GetToken (STRING_TOKEN (CHANGE_REMINDER), gHiiHandle);\r
- SaveConfirmString = GetToken (STRING_TOKEN (SAVE_CONFIRM), gHiiHandle);\r
-\r
do {\r
- CreateDialog (4, TRUE, 0, NULL, &Key, EmptyString, ChangeReminderString, SaveConfirmString, EmptyString);\r
- } while\r
- (((Key.UnicodeChar | UPPER_LOWER_CASE_OFFSET) != (NoResponse[0] | UPPER_LOWER_CASE_OFFSET)) &&\r
- ((Key.UnicodeChar | UPPER_LOWER_CASE_OFFSET) != (YesResponse[0] | UPPER_LOWER_CASE_OFFSET))\r
- );\r
+ DataSavedAction = (UINT32) mFormDisplay->ConfirmDataChange();\r
\r
- //\r
- // If the user hits the YesResponse key\r
- //\r
- if ((Key.UnicodeChar | UPPER_LOWER_CASE_OFFSET) == (YesResponse[0] | UPPER_LOWER_CASE_OFFSET)) {\r
- SubmitForm (NULL, NULL, SystemLevel);\r
- DataSavedAction = BROWSER_SAVE_CHANGES;\r
- } else {\r
- DiscardForm (NULL, NULL, SystemLevel);\r
- DataSavedAction = BROWSER_DISCARD_CHANGES;\r
- gResetRequired = FALSE;\r
- }\r
-\r
- FreePool (YesResponse);\r
- FreePool (NoResponse);\r
- FreePool (EmptyString);\r
- FreePool (SaveConfirmString);\r
- FreePool (ChangeReminderString);\r
+ if (DataSavedAction == BROWSER_SAVE_CHANGES) {\r
+ SubmitForm (NULL, NULL, SystemLevel);\r
+ break;\r
+ } else if (DataSavedAction == BROWSER_DISCARD_CHANGES) {\r
+ DiscardForm (NULL, NULL, SystemLevel);\r
+ break;\r
+ }\r
+ } while (1);\r
\r
return DataSavedAction;\r
}\r
#include <Protocol/SimpleTextOut.h>\r
#include <Protocol/SimpleTextIn.h>\r
#include <Protocol/FormBrowser2.h>\r
-#include <Protocol/FormBrowserEx.h>\r
+#include <Protocol/FormBrowserEx2.h>\r
+#include <Protocol/DisplayProtocol.h>\r
#include <Protocol/DevicePath.h>\r
#include <Protocol/UnicodeCollation.h>\r
#include <Protocol/HiiConfigAccess.h>\r
#include <Library/HiiLib.h>\r
#include <Library/PcdLib.h>\r
#include <Library/DevicePathLib.h>\r
+#include <Library/UefiLib.h>\r
\r
-#include "Colors.h"\r
\r
//\r
// This is the generated header file which includes whatever needs to be exported (strings + IFR)\r
//\r
\r
-extern UINT8 SetupBrowserStrings[];\r
+#define UI_ACTION_NONE 0\r
+#define UI_ACTION_REFRESH_FORM 1\r
+#define UI_ACTION_REFRESH_FORMSET 2\r
+#define UI_ACTION_EXIT 3\r
\r
//\r
-// Screen definitions\r
-//\r
-#define BANNER_HEIGHT 6\r
-#define BANNER_COLUMNS 3\r
-#define BANNER_LEFT_COLUMN_INDENT 1\r
-\r
-#define FRONT_PAGE_HEADER_HEIGHT 6\r
-#define NONE_FRONT_PAGE_HEADER_HEIGHT 3\r
-#define LEFT_SKIPPED_COLUMNS 3\r
-#define FOOTER_HEIGHT 4\r
-#define STATUS_BAR_HEIGHT 1\r
-#define SCROLL_ARROW_HEIGHT 1\r
-#define POPUP_PAD_SPACE_COUNT 5\r
-#define POPUP_FRAME_WIDTH 2\r
-\r
-//\r
-// Definition for function key setting\r
-//\r
-#define NONE_FUNCTION_KEY_SETTING 0\r
-#define ENABLE_FUNCTION_KEY_SETTING 1\r
-\r
-typedef struct {\r
- EFI_GUID FormSetGuid;\r
- UINTN KeySetting;\r
-} FUNCTIION_KEY_SETTING;\r
-\r
-//\r
-// Character definitions\r
-//\r
-#define CHAR_SPACE 0x0020\r
-#define UPPER_LOWER_CASE_OFFSET 0x20\r
-\r
//\r
// Time definitions\r
//\r
#define ONE_SECOND 10000000\r
\r
-//\r
-// Display definitions\r
-//\r
-#define LEFT_HYPER_DELIMITER L'<'\r
-#define RIGHT_HYPER_DELIMITER L'>'\r
-\r
-#define LEFT_ONEOF_DELIMITER L'<'\r
-#define RIGHT_ONEOF_DELIMITER L'>'\r
-\r
-#define LEFT_NUMERIC_DELIMITER L'['\r
-#define RIGHT_NUMERIC_DELIMITER L']'\r
-\r
-#define LEFT_CHECKBOX_DELIMITER L'['\r
-#define RIGHT_CHECKBOX_DELIMITER L']'\r
-\r
-#define CHECK_ON L'X'\r
-#define CHECK_OFF L' '\r
-\r
-#define TIME_SEPARATOR L':'\r
-#define DATE_SEPARATOR L'/'\r
-\r
-#define YES_ANSWER L'Y'\r
-#define NO_ANSWER L'N'\r
-\r
-//\r
-// This is the Input Error Message\r
-//\r
-#define INPUT_ERROR 1\r
-\r
-//\r
-// This is the NV RAM update required Message\r
-//\r
-#define NV_UPDATE_REQUIRED 2\r
-\r
-//\r
-// Refresh the Status Bar with flags\r
-//\r
-#define REFRESH_STATUS_BAR 0xff\r
-\r
-//\r
// Incremental string lenght of ConfigRequest\r
//\r
#define CONFIG_REQUEST_STRING_INCREMENTAL 1024\r
\r
-//\r
-// HII value compare result\r
-//\r
-#define HII_VALUE_UNDEFINED 0\r
-#define HII_VALUE_EQUAL 1\r
-#define HII_VALUE_LESS_THAN 2\r
-#define HII_VALUE_GREATER_THAN 3\r
-\r
//\r
// Incremental size of stack for expression\r
//\r
//\r
// Produced protocol\r
//\r
- EFI_FORM_BROWSER2_PROTOCOL FormBrowser2;\r
- \r
- EFI_FORM_BROWSER_EXTENSION_PROTOCOL FormBrowserEx;\r
+ EFI_FORM_BROWSER2_PROTOCOL FormBrowser2;\r
+ EFI_FORM_BROWSER_EXTENSION_PROTOCOL FormBrowserEx;\r
\r
-} SETUP_DRIVER_PRIVATE_DATA;\r
+ EDKII_FORM_BROWSER_EXTENSION2_PROTOCOL FormBrowserEx2;\r
\r
-typedef struct {\r
- EFI_STRING_ID Banner[BANNER_HEIGHT][BANNER_COLUMNS];\r
-} BANNER_DATA;\r
+} SETUP_DRIVER_PRIVATE_DATA;\r
\r
//\r
// IFR relative definition\r
#define FORM_INCONSISTENT_VALIDATION 0\r
#define FORM_NO_SUBMIT_VALIDATION 1\r
\r
-#define FORMSET_CLASS_PLATFORM_SETUP 0x0001\r
-#define FORMSET_CLASS_FRONT_PAGE 0x0002\r
-\r
-typedef struct {\r
- UINT8 Type;\r
- UINT8 *Buffer;\r
- UINT16 BufferLen;\r
- EFI_IFR_TYPE_VALUE Value;\r
-} EFI_HII_VALUE;\r
-\r
#define NAME_VALUE_NODE_SIGNATURE SIGNATURE_32 ('N', 'V', 'S', 'T')\r
\r
typedef struct {\r
BROWSER_STORAGE *BrowserStorage;\r
\r
CHAR16 *ConfigRequest; // <ConfigRequest> = <ConfigHdr> + <RequestElement>\r
+ CHAR16 *ConfigElements;// Elements need to load initial data.\r
UINTN ElementCount; // Number of <RequestElement> in the <ConfigRequest>\r
UINTN SpareStrLen; // Spare length of ConfigRequest string buffer\r
} FORMSET_STORAGE;\r
typedef struct {\r
UINTN Signature;\r
LIST_ENTRY Link;\r
+ \r
+ EFI_IFR_ONE_OF_OPTION *OpCode; // OneOfOption Data\r
\r
EFI_STRING_ID Text;\r
UINT8 Flags;\r
LIST_ENTRY Link;\r
\r
UINT8 Operand; // The operand (first byte) of this Statement or Question\r
+ EFI_IFR_OP_HEADER *OpCode;\r
\r
//\r
// Statement Header\r
EFI_STRING_ID Help;\r
EFI_STRING_ID TextTwo; // For EFI_IFR_TEXT\r
\r
+ //\r
+ // Fake Question Id, used for statement not has true QuestionId.\r
+ //\r
+ EFI_QUESTION_ID FakeQuestionId;\r
+\r
//\r
// Question Header\r
//\r
EFI_DEFAULT_ID DefaultId; // for EFI_IFR_RESET_BUTTON\r
EFI_GUID RefreshGuid; // for EFI_IFR_REFRESH_ID\r
BOOLEAN Locked; // Whether this statement is locked.\r
+ BOOLEAN ValueChanged; // Whether this statement's value is changed.\r
//\r
// Get from IFR parsing\r
//\r
BOOLEAN ModalForm; // Whether this is a modal form.\r
BOOLEAN Locked; // Whether this form is locked.\r
\r
- BOOLEAN NvUpdateRequired; // Whether this form has NV update request.\r
-\r
LIST_ENTRY ExpressionListHead; // List of Expressions (FORM_EXPRESSION)\r
LIST_ENTRY StatementListHead; // List of Statements and Questions (FORM_BROWSER_STATEMENT)\r
LIST_ENTRY ConfigRequestHead; // List of configreques for all storage.\r
UINTN IfrBinaryLength;\r
UINT8 *IfrBinaryData;\r
\r
+ BOOLEAN QuestionInited; // Have finished question initilization?\r
EFI_GUID Guid;\r
EFI_STRING_ID FormSetTitle;\r
EFI_STRING_ID Help;\r
FORM_BROWSER_STATEMENT *StatementBuffer; // Buffer for all Statements and Questions\r
EXPRESSION_OPCODE *ExpressionBuffer; // Buffer for all Expression OpCode\r
\r
+ LIST_ENTRY StatementListOSF; // Statement list out side of the form.\r
LIST_ENTRY StorageListHead; // Storage list (FORMSET_STORAGE)\r
LIST_ENTRY DefaultStoreListHead; // DefaultStore list (FORMSET_DEFAULTSTORE)\r
LIST_ENTRY FormListHead; // Form list (FORM_BROWSER_FORM)\r
LIST_ENTRY ExpressionListHead; // List of Expressions (FORM_EXPRESSION)\r
} FORM_BROWSER_FORMSET;\r
-\r
#define FORM_BROWSER_FORMSET_FROM_LINK(a) CR (a, FORM_BROWSER_FORMSET, Link, FORM_BROWSER_FORMSET_SIGNATURE)\r
\r
-#define BROWSER_CONTEXT_SIGNATURE SIGNATURE_32 ('B', 'C', 'T', 'X')\r
+typedef struct {\r
+ LIST_ENTRY Link;\r
+ EFI_EVENT RefreshEvent;\r
+} FORM_BROWSER_REFRESH_EVENT_NODE;\r
+\r
+#define FORM_BROWSER_REFRESH_EVENT_FROM_LINK(a) BASE_CR (a, FORM_BROWSER_REFRESH_EVENT_NODE, Link)\r
+\r
\r
typedef struct {\r
- UINTN Signature;\r
- LIST_ENTRY Link;\r
+ EFI_HII_HANDLE Handle;\r
\r
//\r
- // Globals defined in Setup.c\r
+ // Target formset/form/Question information\r
//\r
- BANNER_DATA *BannerData;\r
- UINTN ClassOfVfr;\r
- UINTN FunctionKeySetting;\r
- BOOLEAN ResetRequired;\r
- UINT16 Direction;\r
- EFI_SCREEN_DESCRIPTOR ScreenDimensions;\r
- CHAR16 *EnterString;\r
- CHAR16 *EnterCommitString;\r
- CHAR16 *EnterEscapeString;\r
- CHAR16 *EscapeString;\r
- CHAR16 *MoveHighlight;\r
- CHAR16 *MakeSelection;\r
- CHAR16 *DecNumericInput;\r
- CHAR16 *HexNumericInput;\r
- CHAR16 *ToggleCheckBox;\r
- CHAR16 *PromptForData;\r
- CHAR16 *PromptForPassword;\r
- CHAR16 *PromptForNewPassword;\r
- CHAR16 *ConfirmPassword;\r
- CHAR16 *ConfirmError;\r
- CHAR16 *PassowordInvalid;\r
- CHAR16 *PressEnter;\r
- CHAR16 *EmptyString;\r
- CHAR16 *AreYouSure;\r
- CHAR16 *YesResponse;\r
- CHAR16 *NoResponse;\r
- CHAR16 *MiniString;\r
- CHAR16 *PlusString;\r
- CHAR16 *MinusString;\r
- CHAR16 *AdjustNumber;\r
- CHAR16 *SaveChanges;\r
- CHAR16 *OptionMismatch;\r
- CHAR16 *FormSuppress;\r
- CHAR16 *ProtocolNotFound;\r
- CHAR16 PromptBlockWidth;\r
- CHAR16 OptionBlockWidth;\r
- CHAR16 HelpBlockWidth;\r
- FORM_BROWSER_FORMSET *OldFormSet;\r
+ EFI_GUID FormSetGuid;\r
+ UINT16 FormId;\r
+ UINT16 QuestionId;\r
+ UINTN Sequence; // used for time/date only.\r
+\r
+ UINTN TopRow;\r
+ UINTN BottomRow;\r
+ UINTN PromptCol;\r
+ UINTN OptionCol;\r
+ UINTN CurrentRow;\r
\r
//\r
- // Globals defined in Ui.c\r
+ // Ation for Browser to taken:\r
+ // UI_ACTION_NONE - navigation inside a form\r
+ // UI_ACTION_REFRESH_FORM - re-evaluate expressions and repaint form\r
+ // UI_ACTION_REFRESH_FORMSET - re-parse formset IFR binary\r
//\r
- LIST_ENTRY MenuOption;\r
- VOID *MenuRefreshHead;\r
-} BROWSER_CONTEXT;\r
+ UINTN Action;\r
\r
-#define BROWSER_CONTEXT_FROM_LINK(a) CR (a, BROWSER_CONTEXT, Link, BROWSER_CONTEXT_SIGNATURE)\r
+ //\r
+ // Current selected fomset/form/Question\r
+ //\r
+ FORM_BROWSER_FORMSET *FormSet;\r
+ FORM_BROWSER_FORM *Form;\r
+ FORM_BROWSER_STATEMENT *Statement;\r
\r
-#define BROWSER_HOT_KEY_SIGNATURE SIGNATURE_32 ('B', 'H', 'K', 'S')\r
+ //\r
+ // Whether the Form is editable\r
+ //\r
+ BOOLEAN FormEditable;\r
+\r
+ FORM_ENTRY_INFO *CurrentMenu;\r
+} UI_MENU_SELECTION;\r
+\r
+#define BROWSER_CONTEXT_SIGNATURE SIGNATURE_32 ('B', 'C', 'T', 'X')\r
\r
typedef struct {\r
UINTN Signature;\r
LIST_ENTRY Link;\r
- \r
- EFI_INPUT_KEY *KeyData;\r
- IN UINT32 Action;\r
- IN UINT16 DefaultId;\r
- IN EFI_STRING HelpString;\r
-} BROWSER_HOT_KEY;\r
\r
-#define BROWSER_HOT_KEY_FROM_LINK(a) CR (a, BROWSER_HOT_KEY, Link, BROWSER_HOT_KEY_SIGNATURE)\r
+ //\r
+ // Globals defined in Setup.c\r
+ //\r
+ BOOLEAN ResetRequired;\r
+ BOOLEAN ExitRequired;\r
+ EFI_HII_HANDLE HiiHandle;\r
+ EFI_GUID FormSetGuid;\r
+ EFI_FORM_ID FormId;\r
+ UI_MENU_SELECTION *Selection;\r
+\r
+ LIST_ENTRY FormHistoryList;\r
+} BROWSER_CONTEXT;\r
+\r
+#define BROWSER_CONTEXT_FROM_LINK(a) CR (a, BROWSER_CONTEXT, Link, BROWSER_CONTEXT_SIGNATURE)\r
\r
//\r
// Scope for get defaut value. It may be GetDefaultForNoStorage, GetDefaultForStorage or GetDefaultForAll.\r
} GET_SET_QUESTION_VALUE_WITH;\r
\r
extern EFI_HII_DATABASE_PROTOCOL *mHiiDatabase;\r
-extern EFI_HII_STRING_PROTOCOL *mHiiString;\r
extern EFI_HII_CONFIG_ROUTING_PROTOCOL *mHiiConfigRouting;\r
extern EFI_DEVICE_PATH_FROM_TEXT_PROTOCOL *mPathFromText;\r
+extern EDKII_FORM_DISPLAY_ENGINE_PROTOCOL *mFormDisplay;\r
\r
-extern BANNER_DATA *gBannerData;\r
-extern EFI_HII_HANDLE gFrontPageHandle;\r
-extern UINTN gClassOfVfr;\r
-extern UINTN gFunctionKeySetting;\r
extern BOOLEAN gResetRequired;\r
-extern EFI_HII_HANDLE gHiiHandle;\r
-extern UINT16 gDirection;\r
-extern EFI_SCREEN_DESCRIPTOR gScreenDimensions;\r
+extern BOOLEAN gExitRequired;\r
\r
-extern FORM_BROWSER_FORMSET *gOldFormSet;\r
extern LIST_ENTRY gBrowserFormSetList;\r
extern LIST_ENTRY gBrowserHotKeyList;\r
extern BROWSER_SETTING_SCOPE gBrowserSettingScope;\r
extern EXIT_HANDLER ExitHandlerFunction;\r
-extern UINTN gFooterHeight;\r
-\r
+extern EFI_HII_HANDLE mCurrentHiiHandle;\r
//\r
// Browser Global Strings\r
//\r
-extern CHAR16 *gDiscardFailed;\r
-extern CHAR16 *gDefaultFailed;\r
-extern CHAR16 *gEnterString;\r
-extern CHAR16 *gEnterCommitString;\r
-extern CHAR16 *gEnterEscapeString;\r
-extern CHAR16 *gEscapeString;\r
-extern CHAR16 *gSaveFailed;\r
-extern CHAR16 *gMoveHighlight;\r
-extern CHAR16 *gMakeSelection;\r
-extern CHAR16 *gDecNumericInput;\r
-extern CHAR16 *gHexNumericInput;\r
-extern CHAR16 *gToggleCheckBox;\r
-extern CHAR16 *gPromptForData;\r
-extern CHAR16 *gPromptForPassword;\r
-extern CHAR16 *gPromptForNewPassword;\r
-extern CHAR16 *gConfirmPassword;\r
-extern CHAR16 *gConfirmError;\r
-extern CHAR16 *gPassowordInvalid;\r
-extern CHAR16 *gPressEnter;\r
extern CHAR16 *gEmptyString;\r
-extern CHAR16 *gAreYouSure;\r
-extern CHAR16 *gYesResponse;\r
-extern CHAR16 *gNoResponse;\r
-extern CHAR16 *gMiniString;\r
-extern CHAR16 *gPlusString;\r
-extern CHAR16 *gMinusString;\r
-extern CHAR16 *gAdjustNumber;\r
-extern CHAR16 *gSaveChanges;\r
-extern CHAR16 *gOptionMismatch;\r
-extern CHAR16 *gFormSuppress;\r
-extern CHAR16 *gProtocolNotFound;\r
-\r
-extern CHAR16 gPromptBlockWidth;\r
-extern CHAR16 gOptionBlockWidth;\r
-extern CHAR16 gHelpBlockWidth;\r
\r
extern EFI_GUID gZeroGuid;\r
-extern EFI_GUID gTianoHiiIfrGuid;\r
\r
-#include "Ui.h"\r
+extern UI_MENU_SELECTION *gCurrentSelection;\r
+\r
//\r
// Global Procedure Defines\r
//\r
+#include "Expression.h"\r
\r
/**\r
Initialize the HII String Token to the correct values.\r
VOID\r
);\r
\r
-/**\r
- Prints a unicode string to the default console,\r
- using L"%s" format.\r
-\r
- @param String String pointer.\r
-\r
- @return Length of string printed to the console\r
-\r
-**/\r
-UINTN\r
-PrintString (\r
- IN CHAR16 *String\r
- );\r
-\r
-/**\r
- Prints a chracter to the default console,\r
- using L"%c" format.\r
-\r
- @param Character Character to print.\r
-\r
- @return Length of string printed to the console.\r
-\r
-**/\r
-UINTN\r
-PrintChar (\r
- CHAR16 Character\r
- );\r
-\r
-/**\r
- Prints a formatted unicode string to the default console, at\r
- the supplied cursor position.\r
-\r
- @param Column The cursor position to print the string at.\r
- @param Row The cursor position to print the string at\r
- @param Fmt Format string\r
- @param ... Variable argument list for formating string.\r
-\r
- @return Length of string printed to the console\r
-\r
-**/\r
-UINTN\r
-EFIAPI\r
-PrintAt (\r
- IN UINTN Column,\r
- IN UINTN Row,\r
- IN CHAR16 *Fmt,\r
- ...\r
- );\r
-\r
-/**\r
- Prints a unicode string to the default console, at\r
- the supplied cursor position, using L"%s" format.\r
-\r
- @param Column The cursor position to print the string at.\r
- @param Row The cursor position to print the string at\r
- @param String String pointer.\r
-\r
- @return Length of string printed to the console\r
-\r
-**/\r
-UINTN\r
-PrintStringAt (\r
- IN UINTN Column,\r
- IN UINTN Row,\r
- IN CHAR16 *String\r
- );\r
-\r
-/**\r
- Prints a chracter to the default console, at\r
- the supplied cursor position, using L"%c" format.\r
-\r
- @param Column The cursor position to print the string at.\r
- @param Row The cursor position to print the string at.\r
- @param Character Character to print.\r
-\r
- @return Length of string printed to the console.\r
-\r
-**/\r
-UINTN\r
-PrintCharAt (\r
- IN UINTN Column,\r
- IN UINTN Row,\r
- CHAR16 Character\r
- );\r
-\r
/**\r
Parse opcodes in the formset IFR binary.\r
\r
IN OUT FORM_BROWSER_FORMSET *FormSet\r
);\r
\r
-/**\r
- This function displays the page frame.\r
-\r
- @param Selection Selection contains the information about \r
- the Selection, form and formset to be displayed.\r
- Selection action may be updated in retrieve callback.\r
-**/\r
-VOID\r
-DisplayPageFrame (\r
- IN UI_MENU_SELECTION *Selection\r
- );\r
\r
/**\r
Create a new string in HII Package List.\r
IN EFI_HII_HANDLE HiiHandle\r
);\r
\r
-/**\r
- Draw a pop up windows based on the dimension, number of lines and\r
- strings specified.\r
-\r
- @param RequestedWidth The width of the pop-up.\r
- @param NumberOfLines The number of lines.\r
- @param Marker The variable argument list for the list of string to be printed.\r
-\r
-**/\r
-VOID\r
-CreateSharedPopUp (\r
- IN UINTN RequestedWidth,\r
- IN UINTN NumberOfLines,\r
- IN VA_LIST Marker\r
- );\r
-\r
-/**\r
- Routine used to abstract a generic dialog interface and return the selected key or string\r
-\r
- @param NumberOfLines The number of lines for the dialog box\r
- @param HotKey Defines whether a single character is parsed\r
- (TRUE) and returned in KeyValue or a string is\r
- returned in StringBuffer. Two special characters\r
- are considered when entering a string, a SCAN_ESC\r
- and an CHAR_CARRIAGE_RETURN. SCAN_ESC terminates\r
- string input and returns\r
- @param MaximumStringSize The maximum size in bytes of a typed in string\r
- (each character is a CHAR16) and the minimum\r
- string returned is two bytes\r
- @param StringBuffer The passed in pointer to the buffer which will\r
- hold the typed in string if HotKey is FALSE\r
- @param KeyValue The EFI_KEY value returned if HotKey is TRUE..\r
- @param ... A series of (quantity == NumberOfLines) text\r
- strings which will be used to construct the dialog\r
- box\r
-\r
- @retval EFI_SUCCESS Displayed dialog and received user interaction\r
- @retval EFI_INVALID_PARAMETER One of the parameters was invalid (e.g.\r
- (StringBuffer == NULL) && (HotKey == FALSE))\r
- @retval EFI_DEVICE_ERROR User typed in an ESC character to exit the routine\r
-\r
-**/\r
-EFI_STATUS\r
-EFIAPI\r
-CreateDialog (\r
- IN UINTN NumberOfLines,\r
- IN BOOLEAN HotKey,\r
- IN UINTN MaximumStringSize,\r
- OUT CHAR16 *StringBuffer,\r
- OUT EFI_INPUT_KEY *KeyValue,\r
- ...\r
- );\r
-\r
/**\r
Get Value for given Name from a NameValue Storage.\r
\r
@param Name The Name.\r
@param Value The Value to set.\r
@param SetValueTo Whether update editValue or Value.\r
+ @param ReturnNode The node use the input name.\r
\r
@retval EFI_SUCCESS Value found for given Name.\r
@retval EFI_NOT_FOUND No such Name found in NameValue storage.\r
**/\r
EFI_STATUS\r
SetValueByName (\r
- IN BROWSER_STORAGE *Storage,\r
- IN CHAR16 *Name,\r
- IN CHAR16 *Value,\r
- IN GET_SET_QUESTION_VALUE_WITH SetValueTo\r
+ IN BROWSER_STORAGE *Storage,\r
+ IN CHAR16 *Name,\r
+ IN CHAR16 *Value,\r
+ IN GET_SET_QUESTION_VALUE_WITH SetValueTo,\r
+ OUT NAME_VALUE_NODE **ReturnNode\r
+ );\r
+\r
+/**\r
+ Validate whether this question's value has changed.\r
+\r
+ @param FormSet FormSet data structure.\r
+ @param Form Form data structure.\r
+ @param Question Question to be initialized.\r
+ @param GetValueFrom Where to get value, may from editbuffer, buffer or hii driver.\r
+\r
+ @retval TRUE Question's value has changed.\r
+ @retval FALSE Question's value has not changed\r
+\r
+**/\r
+BOOLEAN\r
+IsQuestionValueChanged (\r
+ IN FORM_BROWSER_FORMSET *FormSet,\r
+ IN FORM_BROWSER_FORM *Form,\r
+ IN OUT FORM_BROWSER_STATEMENT *Question,\r
+ IN GET_SET_QUESTION_VALUE_WITH GetValueFrom\r
);\r
\r
/**\r
\r
@param FormSet FormSet data structure.\r
\r
- @retval EFI_SUCCESS The function completed successfully.\r
-\r
**/\r
-EFI_STATUS\r
+VOID\r
InitializeCurrentSetting (\r
IN OUT FORM_BROWSER_FORMSET *FormSet\r
);\r
GUID), take the first FormSet found in package\r
list.\r
@param FormSet FormSet data structure.\r
- @param UpdateGlobalVar Whether need to update the global variable.\r
\r
@retval EFI_SUCCESS The function completed successfully.\r
@retval EFI_NOT_FOUND The specified FormSet could not be found.\r
InitializeFormSet (\r
IN EFI_HII_HANDLE Handle,\r
IN OUT EFI_GUID *FormSetGuid,\r
- OUT FORM_BROWSER_FORMSET *FormSet,\r
- IN BOOLEAN UpdateGlobalVar \r
+ OUT FORM_BROWSER_FORMSET *FormSet \r
);\r
\r
/**\r
@param Storage The Storage to be conveted.\r
@param ConfigResp The returned <ConfigResp>.\r
@param ConfigRequest The ConfigRequest string.\r
+ @param GetEditBuf Get the data from editbuffer or buffer.\r
\r
@retval EFI_SUCCESS Convert success.\r
@retval EFI_INVALID_PARAMETER Incorrect storage type.\r
StorageToConfigResp (\r
IN BROWSER_STORAGE *Storage,\r
IN CHAR16 **ConfigResp,\r
- IN CHAR16 *ConfigRequest\r
+ IN CHAR16 *ConfigRequest,\r
+ IN BOOLEAN GetEditBuf\r
);\r
\r
/**\r
@param FormSet FormSet data structure.\r
@param Storage Buffer Storage.\r
\r
- @retval EFI_SUCCESS The function completed successfully.\r
-\r
**/\r
-EFI_STATUS\r
+VOID\r
LoadStorage (\r
IN FORM_BROWSER_FORMSET *FormSet,\r
IN FORMSET_STORAGE *Storage\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 Repaint Whether need to repaint the menu.\r
- @param NewLine Whether need to show at new line.\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 Need return.\r
- @retval FALSE No need to return.\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 BOOLEAN *Repaint, \r
- IN BOOLEAN *NewLine \r
+ IN OUT UI_MENU_SELECTION *Selection,\r
+ IN BROWSER_SETTING_SCOPE SettingLevel\r
);\r
\r
/**\r
- check whether the formset need to update the NV.\r
+ check whether the form need to update the NV.\r
\r
- @param FormSet FormSet data structure.\r
- @param SetValue Whether set new value or clear old value.\r
+ @param Form Form data structure.\r
\r
+ @retval TRUE Need to update the NV.\r
+ @retval FALSE No need to update the NV.\r
**/\r
-VOID\r
-UpdateNvInfoInForm (\r
- IN FORM_BROWSER_FORMSET *FormSet,\r
- IN BOOLEAN SetValue\r
+BOOLEAN\r
+IsNvUpdateRequiredForForm (\r
+ IN FORM_BROWSER_FORM *Form\r
);\r
\r
/**\r
@retval TRUE Need to update the NV.\r
@retval FALSE No need to update the NV.\r
**/\r
-BOOLEAN \r
-IsNvUpdateRequired (\r
+BOOLEAN\r
+IsNvUpdateRequiredForFormSet (\r
IN FORM_BROWSER_FORMSET *FormSet\r
);\r
\r
+/**\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
+BOOLEAN \r
+IsStorageDataChangedForFormSet (\r
+ IN FORM_BROWSER_FORMSET *FormSet\r
+ );\r
+\r
/**\r
Call the call back function for the question and process the return action.\r
\r
IN EXIT_HANDLER Handler\r
);\r
\r
+/**\r
+ \r
+ Check whether the browser data has been modified. \r
+\r
+ @retval TRUE Browser data is changed.\r
+ @retval FALSE No browser data is changed.\r
+\r
+**/\r
+BOOLEAN \r
+EFIAPI\r
+IsBrowserDataModified (\r
+ VOID\r
+ );\r
+\r
+/**\r
+ \r
+ Execute the action requested by the Action parameter. \r
+\r
+ @param[in] Action Execute the request action.\r
+ @param[in] DefaultId The default Id info when need to load default value.\r
+\r
+ @retval EFI_SUCCESS Execute the request action succss.\r
+ @retval EFI_INVALID_PARAMETER The input action value is invalid.\r
+\r
+**/\r
+EFI_STATUS \r
+EFIAPI\r
+ExecuteAction (\r
+ IN UINT32 Action,\r
+ IN UINT16 DefaultId\r
+ );\r
+\r
/**\r
Create reminder to let user to choose save or discard the changed browser data.\r
Caller can use it to actively check the changed browser data.\r
IN EFI_INPUT_KEY *KeyData\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
+/**\r
+ Password may be stored as encrypted by Configuration Driver. When change a\r
+ password, user will be challenged with old password. To validate user input old\r
+ password, we will send the clear text to Configuration Driver via Callback().\r
+ Configuration driver is responsible to check the passed in password and return\r
+ the validation result. If validation pass, state machine in password Callback()\r
+ will transit from BROWSER_STATE_VALIDATE_PASSWORD to BROWSER_STATE_SET_PASSWORD.\r
+ After user type in new password twice, Callback() will be invoked to send the\r
+ new password to Configuration Driver.\r
+\r
+ @param Selection Pointer to UI_MENU_SELECTION.\r
+ @param MenuOption The MenuOption for this password Question.\r
+ @param String The clear text of password.\r
+\r
+ @retval EFI_NOT_AVAILABLE_YET Callback() request to terminate password input.\r
+ @return In state of BROWSER_STATE_VALIDATE_PASSWORD:\r
+ @retval EFI_SUCCESS Password correct, Browser will prompt for new\r
+ password.\r
+ @retval EFI_NOT_READY Password incorrect, Browser will show error\r
+ message.\r
+ @retval Other Browser will do nothing.\r
+ @return In state of BROWSER_STATE_SET_PASSWORD:\r
+ @retval EFI_SUCCESS Set password success.\r
+ @retval Other Set password failed.\r
+\r
+**/\r
+EFI_STATUS\r
+PasswordCallback (\r
+ IN UI_MENU_SELECTION *Selection,\r
+ IN FORM_BROWSER_STATEMENT *Question,\r
+ IN CHAR16 *String\r
+ );\r
+\r
+/**\r
+ Display error message for invalid password.\r
+\r
+**/\r
+VOID\r
+PasswordInvalid (\r
+ VOID\r
+ );\r
+\r
+/**\r
+ The worker function that send the displays to the screen. On output,\r
+ the selection made by user is returned.\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
+ @retval EFI_SUCCESS The page is displayed successfully.\r
+ @return Other value if the page failed to be diplayed.\r
+\r
+**/\r
+EFI_STATUS\r
+SetupBrowser (\r
+ IN OUT UI_MENU_SELECTION *Selection\r
+ );\r
+ \r
+/**\r
+ Free up the resource allocated for all strings required\r
+ by Setup Browser.\r
+\r
+**/\r
+VOID\r
+FreeBrowserStrings (\r
+ VOID\r
+ );\r
+\r
+/**\r
+ Create a menu with specified formset GUID and form ID, and add it as a child\r
+ of the given parent menu.\r
+\r
+ @param HiiHandle Hii handle related to this formset.\r
+ @param FormSetGuid The Formset Guid of menu to be added.\r
+ @param FormId The Form ID of menu to be added.\r
+ @param QuestionId The question id of this menu to be added.\r
+\r
+ @return A pointer to the newly added menu or NULL if memory is insufficient.\r
+\r
+**/\r
+FORM_ENTRY_INFO *\r
+UiAddMenuList (\r
+ IN EFI_HII_HANDLE HiiHandle,\r
+ IN EFI_GUID *FormSetGuid,\r
+ IN UINT16 FormId,\r
+ IN UINT16 QuestionId\r
+ );\r
+\r
+/**\r
+ Search Menu with given FormSetGuid and FormId in all cached menu list.\r
+\r
+ @param HiiHandle HiiHandle for FormSet.\r
+ @param FormSetGuid The Formset GUID of the menu to search.\r
+ @param FormId The Form ID of menu to search.\r
+\r
+ @return A pointer to menu found or NULL if not found.\r
+\r
+**/\r
+FORM_ENTRY_INFO *\r
+UiFindMenuList (\r
+ IN EFI_HII_HANDLE HiiHandle, \r
+ IN EFI_GUID *FormSetGuid,\r
+ IN UINT16 FormId\r
+ );\r
+\r
+/**\r
+ Free Menu list linked list.\r
+\r
+ @param MenuListHead One Menu list point in the menu list.\r
+\r
+**/\r
+VOID\r
+UiFreeMenuList (\r
+ LIST_ENTRY *MenuListHead\r
+ );\r
+\r
+/**\r
+ Find parent menu for current menu.\r
+\r
+ @param CurrentMenu Current Menu\r
+\r
+ @retval The parent menu for current menu.\r
+**/\r
+FORM_ENTRY_INFO *\r
+UiFindParentMenu (\r
+ IN FORM_ENTRY_INFO *CurrentMenu\r
+ );\r
+\r
+/**\r
+ Search an Option of a Question by its value.\r
+\r
+ @param Question The Question\r
+ @param OptionValue Value for Option to be searched.\r
+\r
+ @retval Pointer Pointer to the found Option.\r
+ @retval NULL Option not found.\r
+\r
+**/\r
+QUESTION_OPTION *\r
+ValueToOption (\r
+ IN FORM_BROWSER_STATEMENT *Question,\r
+ IN EFI_HII_VALUE *OptionValue\r
+ );\r
+/**\r
+ Return data element in an Array by its Index.\r
+\r
+ @param Array The data array.\r
+ @param Type Type of the data in this array.\r
+ @param Index Zero based index for data in this array.\r
+\r
+ @retval Value The data to be returned\r
+\r
+**/\r
+UINT64\r
+GetArrayData (\r
+ IN VOID *Array,\r
+ IN UINT8 Type,\r
+ IN UINTN Index\r
+ );\r
+\r
+/**\r
+ Set value of a data element in an Array by its Index.\r
+\r
+ @param Array The data array.\r
+ @param Type Type of the data in this array.\r
+ @param Index Zero based index for data in this array.\r
+ @param Value The value to be set.\r
+\r
+**/\r
+VOID\r
+SetArrayData (\r
+ IN VOID *Array,\r
+ IN UINT8 Type,\r
+ IN UINTN Index,\r
+ IN UINT64 Value\r
+ );\r
+\r
+/**\r
+ Compare two Hii value.\r
+ \r
+ @param Value1 Expression value to compare on left-hand.\r
+ @param Value2 Expression value to compare on right-hand.\r
+ @param Result Return value after compare.\r
+ retval 0 Two operators equal.\r
+ return Positive value if Value1 is greater than Value2.\r
+ retval Negative value if Value1 is less than Value2.\r
+ @param HiiHandle Only required for string compare.\r
+ \r
+ @retval other Could not perform compare on two values.\r
+ @retval EFI_SUCCESS Compare the value success.\r
+ \r
+**/\r
+EFI_STATUS\r
+CompareHiiValue (\r
+ IN EFI_HII_VALUE *Value1,\r
+ IN EFI_HII_VALUE *Value2,\r
+ OUT INTN *Result,\r
+ IN EFI_HII_HANDLE HiiHandle OPTIONAL\r
+ );\r
+\r
+/**\r
+ Perform Password check. \r
+ Passwork may be encrypted by driver that requires the specific check.\r
+ \r
+ @param Form Form where Password Statement is in.\r
+ @param Statement Password statement\r
+ @param PasswordString Password string to be checked. It may be NULL.\r
+ NULL means to restore password.\r
+ "" string can be used to checked whether old password does exist.\r
+ \r
+ @return Status Status of Password check.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+PasswordCheck (\r
+ IN FORM_DISPLAY_ENGINE_FORM *Form,\r
+ IN FORM_DISPLAY_ENGINE_STATEMENT *Statement,\r
+ IN EFI_STRING PasswordString OPTIONAL\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
+/**\r
+\r
+ Initialize the Display form structure data.\r
+\r
+**/\r
+VOID\r
+InitializeDisplayFormData (\r
+ VOID\r
+ );\r
+\r
+\r
/**\r
Base on the current formset info, clean the ConfigRequest string in browser storage.\r
\r
CleanBrowserStorage (\r
IN OUT FORM_BROWSER_FORMSET *FormSet\r
);\r
-\r
+ \r
#endif\r
BASE_NAME = SetupBrowser\r
FILE_GUID = EBf342FE-B1D3-4EF8-957C-8048606FF671\r
MODULE_TYPE = DXE_DRIVER\r
- VERSION_STRING = 1.0\r
+ VERSION_STRING = 2.0\r
ENTRY_POINT = InitializeSetup\r
\r
#\r
#\r
\r
[Sources]\r
- SetupBrowserStr.uni\r
Setup.c\r
Setup.h\r
IfrParse.c\r
Expression.c\r
- InputHandler.c\r
- Print.c\r
Presentation.c\r
- ProcessOptions.c\r
- Ui.c\r
- Ui.h\r
- Colors.h\r
-\r
+ Expression.h\r
\r
[Packages]\r
MdePkg/MdePkg.dec\r
HiiLib\r
DevicePathLib\r
PcdLib\r
+ UefiLib\r
\r
[Guids]\r
- gEfiIfrTianoGuid ## CONSUMES ## GUID\r
gEfiIfrFrameworkGuid ## CONSUMES ## GUID\r
gEfiHiiPlatformSetupFormsetGuid\r
gEfiHiiStandardFormGuid ## SOMETIMES_CONSUMES ## GUID\r
\r
[Protocols]\r
gEfiHiiConfigAccessProtocolGuid ## CONSUMES\r
- gEfiHiiStringProtocolGuid ## CONSUMES\r
gEfiFormBrowser2ProtocolGuid ## PRODUCES\r
- gEfiFormBrowserExProtocolGuid ## PRODUCES\r
+ gEdkiiFormBrowserEx2ProtocolGuid ## PRODUCES\r
gEfiHiiConfigRoutingProtocolGuid ## CONSUMES\r
gEfiHiiDatabaseProtocolGuid ## CONSUMES\r
gEfiUnicodeCollation2ProtocolGuid ## CONSUMES\r
gEfiUserManagerProtocolGuid ## SOMETIMES_CONSUMES\r
gEfiDevicePathFromTextProtocolGuid ## SOMETIMES_CONSUMES\r
+ gEdkiiFormDisplayEngineProtocolGuid ## PRODUCE\r
+ gEfiFormBrowserExProtocolGuid ## PRODUCE\r
\r
[FeaturePcd]\r
gEfiMdeModulePkgTokenSpaceGuid.PcdFrameworkCompatibilitySupport ## CONSUMES\r
- gEfiMdeModulePkgTokenSpaceGuid.PcdBrowserGrayOutTextStatement ## CONSUMES\r
- gEfiMdeModulePkgTokenSpaceGuid.PcdBrowerGrayOutReadOnlyMenu ## CONSUMES\r
-\r
-[Pcd]\r
- gEfiMdeModulePkgTokenSpaceGuid.PcdBrowserSubtitleTextColor ## CONSUMES\r
- gEfiMdeModulePkgTokenSpaceGuid.PcdBrowserFieldTextColor ## CONSUMES\r
- gEfiMdeModulePkgTokenSpaceGuid.PcdBrowserFieldTextHighlightColor ## CONSUMES\r
- gEfiMdeModulePkgTokenSpaceGuid.PcdBrowserFieldBackgroundHighlightColor ## CONSUMES\r
\r
[Depex]\r
gEfiHiiDatabaseProtocolGuid AND gEfiHiiConfigRoutingProtocolGuid\r
+++ /dev/null
-/** @file\r
-Utility functions for User Interface functions.\r
-\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
-THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
-WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
-\r
-**/\r
-\r
-#include "Setup.h"\r
-\r
-LIST_ENTRY gMenuOption;\r
-LIST_ENTRY gMenuList;\r
-MENU_REFRESH_ENTRY *gMenuRefreshHead; // Menu list used for refresh timer opcode.\r
-MENU_REFRESH_ENTRY *gMenuEventGuidRefreshHead; // Menu list used for refresh event guid opcode.\r
-\r
-//\r
-// Search table for UiDisplayMenu()\r
-//\r
-SCAN_CODE_TO_SCREEN_OPERATION gScanCodeToOperation[] = {\r
- {\r
- SCAN_UP,\r
- UiUp,\r
- },\r
- {\r
- SCAN_DOWN,\r
- UiDown,\r
- },\r
- {\r
- SCAN_PAGE_UP,\r
- UiPageUp,\r
- },\r
- {\r
- SCAN_PAGE_DOWN,\r
- UiPageDown,\r
- },\r
- {\r
- SCAN_ESC,\r
- UiReset,\r
- },\r
- {\r
- SCAN_LEFT,\r
- UiLeft,\r
- },\r
- {\r
- SCAN_RIGHT,\r
- UiRight,\r
- }\r
-};\r
-\r
-UINTN mScanCodeNumber = sizeof (gScanCodeToOperation) / sizeof (gScanCodeToOperation[0]);\r
-\r
-SCREEN_OPERATION_T0_CONTROL_FLAG gScreenOperationToControlFlag[] = {\r
- {\r
- UiNoOperation,\r
- CfUiNoOperation,\r
- },\r
- {\r
- UiSelect,\r
- CfUiSelect,\r
- },\r
- {\r
- UiUp,\r
- CfUiUp,\r
- },\r
- {\r
- UiDown,\r
- CfUiDown,\r
- },\r
- {\r
- UiLeft,\r
- CfUiLeft,\r
- },\r
- {\r
- UiRight,\r
- CfUiRight,\r
- },\r
- {\r
- UiReset,\r
- CfUiReset,\r
- },\r
- {\r
- UiPageUp,\r
- CfUiPageUp,\r
- },\r
- {\r
- UiPageDown,\r
- CfUiPageDown\r
- }, \r
- {\r
- UiHotKey,\r
- CfUiHotKey\r
- }\r
-};\r
-\r
-BOOLEAN mInputError;\r
-BOOLEAN GetLineByWidthFinished = FALSE;\r
-\r
-\r
-/**\r
- Set Buffer to Value for Size bytes.\r
-\r
- @param Buffer Memory to set.\r
- @param Size Number of bytes to set\r
- @param Value Value of the set operation.\r
-\r
-**/\r
-VOID\r
-SetUnicodeMem (\r
- IN VOID *Buffer,\r
- IN UINTN Size,\r
- IN CHAR16 Value\r
- )\r
-{\r
- CHAR16 *Ptr;\r
-\r
- Ptr = Buffer;\r
- while ((Size--) != 0) {\r
- *(Ptr++) = Value;\r
- }\r
-}\r
-\r
-\r
-/**\r
- Initialize Menu option list.\r
-\r
-**/\r
-VOID\r
-UiInitMenu (\r
- VOID\r
- )\r
-{\r
- InitializeListHead (&gMenuOption);\r
-}\r
-\r
-\r
-/**\r
- Free Menu option linked list.\r
-\r
-**/\r
-VOID\r
-UiFreeMenu (\r
- VOID\r
- )\r
-{\r
- UI_MENU_OPTION *MenuOption;\r
-\r
- while (!IsListEmpty (&gMenuOption)) {\r
- MenuOption = MENU_OPTION_FROM_LINK (gMenuOption.ForwardLink);\r
- RemoveEntryList (&MenuOption->Link);\r
-\r
- //\r
- // We allocated space for this description when we did a GetToken, free it here\r
- //\r
- if (MenuOption->Skip != 0) {\r
- //\r
- // For date/time, MenuOption->Description is shared by three Menu Options\r
- // Data format : [01/02/2004] [11:22:33]\r
- // Line number : 0 0 1 0 0 1\r
- //\r
- FreePool (MenuOption->Description);\r
- }\r
- FreePool (MenuOption);\r
- }\r
-}\r
-\r
-\r
-/**\r
- Create a menu with specified formset GUID and form ID, and add it as a child\r
- of the given parent menu.\r
-\r
- @param Parent The parent of menu to be added.\r
- @param HiiHandle Hii handle related to this formset.\r
- @param FormSetGuid The Formset Guid of menu to be added.\r
- @param FormId The Form ID of menu to be added.\r
-\r
- @return A pointer to the newly added menu or NULL if memory is insufficient.\r
-\r
-**/\r
-UI_MENU_LIST *\r
-UiAddMenuList (\r
- IN OUT UI_MENU_LIST *Parent,\r
- IN EFI_HII_HANDLE HiiHandle,\r
- IN EFI_GUID *FormSetGuid,\r
- IN UINT16 FormId\r
- )\r
-{\r
- UI_MENU_LIST *MenuList;\r
-\r
- MenuList = AllocateZeroPool (sizeof (UI_MENU_LIST));\r
- if (MenuList == NULL) {\r
- return NULL;\r
- }\r
-\r
- MenuList->Signature = UI_MENU_LIST_SIGNATURE;\r
- InitializeListHead (&MenuList->ChildListHead);\r
-\r
- MenuList->HiiHandle = HiiHandle;\r
- CopyMem (&MenuList->FormSetGuid, FormSetGuid, sizeof (EFI_GUID));\r
- MenuList->FormId = FormId;\r
- MenuList->Parent = Parent;\r
-\r
- if (Parent == NULL) {\r
- //\r
- // If parent is not specified, it is the root Form of a Formset\r
- //\r
- InsertTailList (&gMenuList, &MenuList->Link);\r
- } else {\r
- InsertTailList (&Parent->ChildListHead, &MenuList->Link);\r
- }\r
-\r
- return MenuList;\r
-}\r
-\r
-\r
-/**\r
- Search Menu with given FormId, FormSetGuid and Handle in all cached menu list.\r
-\r
- @param Parent The parent of menu to search.\r
- @param Handle Hii handle related to this formset.\r
- @param FormSetGuid The Formset GUID of the menu to search. \r
- @param FormId The Form ID of menu to search.\r
-\r
- @return A pointer to menu found or NULL if not found.\r
-\r
-**/\r
-UI_MENU_LIST *\r
-UiFindChildMenuList (\r
- IN UI_MENU_LIST *Parent,\r
- IN EFI_HII_HANDLE Handle,\r
- IN EFI_GUID *FormSetGuid, \r
- IN UINT16 FormId\r
- )\r
-{\r
- LIST_ENTRY *Link;\r
- UI_MENU_LIST *Child;\r
- UI_MENU_LIST *MenuList;\r
-\r
- ASSERT (Parent != NULL);\r
-\r
- if (Parent->FormId == FormId && CompareGuid (FormSetGuid, &Parent->FormSetGuid) && Parent->HiiHandle == Handle) {\r
- return Parent;\r
- }\r
-\r
- Link = GetFirstNode (&Parent->ChildListHead);\r
- while (!IsNull (&Parent->ChildListHead, Link)) {\r
- Child = UI_MENU_LIST_FROM_LINK (Link);\r
-\r
- MenuList = UiFindChildMenuList (Child, Handle, FormSetGuid, FormId);\r
- if (MenuList != NULL) {\r
- return MenuList;\r
- }\r
-\r
- Link = GetNextNode (&Parent->ChildListHead, Link);\r
- }\r
-\r
- return NULL;\r
-}\r
-\r
-\r
-/**\r
- Search Menu with given Handle, FormSetGuid and FormId in all cached menu list.\r
-\r
- @param Handle Hii handle related to this formset.\r
- @param FormSetGuid The Formset GUID of the menu to search.\r
- @param FormId The Form ID of menu to search.\r
-\r
- @return A pointer to menu found or NULL if not found.\r
-\r
-**/\r
-UI_MENU_LIST *\r
-UiFindMenuList (\r
- IN EFI_HII_HANDLE Handle,\r
- IN EFI_GUID *FormSetGuid,\r
- IN UINT16 FormId\r
- )\r
-{\r
- LIST_ENTRY *Link;\r
- UI_MENU_LIST *MenuList;\r
- UI_MENU_LIST *Child;\r
-\r
- Link = GetFirstNode (&gMenuList);\r
- while (!IsNull (&gMenuList, Link)) {\r
- MenuList = UI_MENU_LIST_FROM_LINK (Link);\r
-\r
- Child = UiFindChildMenuList(MenuList, Handle, FormSetGuid, FormId);\r
- if (Child != NULL) {\r
-\r
- //\r
- // If this form already in the menu history list,\r
- // just free the list between old this form.\r
- //\r
- UiFreeMenuList(&Child->ChildListHead);\r
- return Child;\r
- }\r
-\r
- Link = GetNextNode (&gMenuList, Link);\r
- }\r
-\r
- return NULL;\r
-}\r
-\r
-/**\r
- Free Menu list linked list.\r
-\r
- @param MenuListHead One Menu list point in the menu list.\r
-\r
-**/\r
-VOID\r
-UiFreeMenuList (\r
- LIST_ENTRY *MenuListHead\r
- )\r
-{\r
- UI_MENU_LIST *MenuList;\r
-\r
- while (!IsListEmpty (MenuListHead)) {\r
- MenuList = UI_MENU_LIST_FROM_LINK (MenuListHead->ForwardLink);\r
- RemoveEntryList (&MenuList->Link);\r
- \r
- UiFreeMenuList(&MenuList->ChildListHead);\r
- FreePool (MenuList);\r
- }\r
-\r
-}\r
-\r
-/**\r
- Free Menu option linked list.\r
-\r
-**/\r
-VOID\r
-UiFreeRefreshList (\r
- VOID\r
- )\r
-{\r
- MENU_REFRESH_ENTRY *OldMenuRefreshEntry;\r
-\r
- while (gMenuRefreshHead != NULL) {\r
- OldMenuRefreshEntry = gMenuRefreshHead->Next;\r
- FreePool (gMenuRefreshHead);\r
- gMenuRefreshHead = OldMenuRefreshEntry;\r
- }\r
-\r
- while (gMenuEventGuidRefreshHead != NULL) {\r
- OldMenuRefreshEntry = gMenuEventGuidRefreshHead->Next;\r
- if (gMenuEventGuidRefreshHead != NULL) {\r
- gBS->CloseEvent(gMenuEventGuidRefreshHead->Event);\r
- }\r
- FreePool (gMenuEventGuidRefreshHead);\r
- gMenuEventGuidRefreshHead = OldMenuRefreshEntry;\r
- }\r
-}\r
-\r
-\r
-/**\r
- Process option string for date/time opcode.\r
-\r
- @param MenuOption Menu option point to date/time.\r
- @param OptionString Option string input for process.\r
- @param AddOptCol Whether need to update MenuOption->OptCol. \r
-\r
-**/\r
-VOID \r
-ProcessStringForDateTime (\r
- UI_MENU_OPTION *MenuOption,\r
- CHAR16 *OptionString,\r
- BOOLEAN AddOptCol\r
- )\r
-{\r
- UINTN Index;\r
- UINTN Count;\r
- FORM_BROWSER_STATEMENT *Statement;\r
-\r
- ASSERT (MenuOption != NULL && OptionString != NULL);\r
- \r
- Statement = MenuOption->ThisTag;\r
- \r
- //\r
- // If leading spaces on OptionString - remove the spaces\r
- //\r
- for (Index = 0; OptionString[Index] == L' '; Index++) {\r
- //\r
- // Base on the blockspace to get the option column info.\r
- //\r
- if (AddOptCol) {\r
- MenuOption->OptCol++;\r
- }\r
- }\r
- \r
- for (Count = 0; OptionString[Index] != CHAR_NULL; Index++) {\r
- OptionString[Count] = OptionString[Index];\r
- Count++;\r
- }\r
- OptionString[Count] = CHAR_NULL;\r
- \r
- //\r
- // Enable to suppress field in the opcode base on the flag.\r
- //\r
- if (Statement->Operand == EFI_IFR_DATE_OP) {\r
- //\r
- // OptionString format is: <**: **: ****>\r
- // |month|day|year|\r
- // 4 3 5\r
- //\r
- if ((Statement->Flags & EFI_QF_DATE_MONTH_SUPPRESS) && (MenuOption->Sequence == 0)) {\r
- //\r
- // At this point, only "<**:" in the optionstring. \r
- // Clean the day's ** field, after clean, the format is "< :"\r
- //\r
- SetUnicodeMem (&OptionString[1], 2, L' ');\r
- } else if ((Statement->Flags & EFI_QF_DATE_DAY_SUPPRESS) && (MenuOption->Sequence == 1)) {\r
- //\r
- // At this point, only "**:" in the optionstring. \r
- // Clean the month's "**" field, after clean, the format is " :"\r
- // \r
- SetUnicodeMem (&OptionString[0], 2, L' ');\r
- } else if ((Statement->Flags & EFI_QF_DATE_YEAR_SUPPRESS) && (MenuOption->Sequence == 2)) {\r
- //\r
- // At this point, only "****>" in the optionstring. \r
- // Clean the year's "****" field, after clean, the format is " >"\r
- // \r
- SetUnicodeMem (&OptionString[0], 4, L' ');\r
- }\r
- } else if (Statement->Operand == EFI_IFR_TIME_OP) {\r
- //\r
- // OptionString format is: <**: **: **>\r
- // |hour|minute|second|\r
- // 4 3 3\r
- //\r
- if ((Statement->Flags & QF_TIME_HOUR_SUPPRESS) && (MenuOption->Sequence == 0)) {\r
- //\r
- // At this point, only "<**:" in the optionstring. \r
- // Clean the hour's ** field, after clean, the format is "< :"\r
- //\r
- SetUnicodeMem (&OptionString[1], 2, L' ');\r
- } else if ((Statement->Flags & QF_TIME_MINUTE_SUPPRESS) && (MenuOption->Sequence == 1)) {\r
- //\r
- // At this point, only "**:" in the optionstring. \r
- // Clean the minute's "**" field, after clean, the format is " :"\r
- // \r
- SetUnicodeMem (&OptionString[0], 2, L' ');\r
- } else if ((Statement->Flags & QF_TIME_SECOND_SUPPRESS) && (MenuOption->Sequence == 2)) {\r
- //\r
- // At this point, only "**>" in the optionstring. \r
- // Clean the second's "**" field, after clean, the format is " >"\r
- // \r
- SetUnicodeMem (&OptionString[0], 2, L' ');\r
- }\r
- }\r
-}\r
-\r
-/**\r
- Refresh question.\r
-\r
- @param MenuRefreshEntry Menu refresh structure which has info about the refresh question.\r
-**/\r
-EFI_STATUS \r
-RefreshQuestion (\r
- IN MENU_REFRESH_ENTRY *MenuRefreshEntry\r
- )\r
-{\r
- CHAR16 *OptionString;\r
- EFI_STATUS Status;\r
- UI_MENU_SELECTION *Selection;\r
- FORM_BROWSER_STATEMENT *Question;\r
-\r
- Selection = MenuRefreshEntry->Selection;\r
- Question = MenuRefreshEntry->MenuOption->ThisTag;\r
-\r
- Status = GetQuestionValue (Selection->FormSet, Selection->Form, Question, GetSetValueWithHiiDriver);\r
- if (EFI_ERROR (Status)) {\r
- return Status;\r
- }\r
-\r
- OptionString = NULL;\r
- ProcessOptions (Selection, MenuRefreshEntry->MenuOption, FALSE, &OptionString);\r
-\r
- if (OptionString != NULL) {\r
- //\r
- // If old Text is longer than new string, need to clean the old string before paint the newer.\r
- // This option is no need for time/date opcode, because time/data opcode has fixed string length.\r
- //\r
- if ((MenuRefreshEntry->MenuOption->ThisTag->Operand != EFI_IFR_DATE_OP) &&\r
- (MenuRefreshEntry->MenuOption->ThisTag->Operand != EFI_IFR_TIME_OP)) {\r
- ClearLines (\r
- MenuRefreshEntry->CurrentColumn, \r
- MenuRefreshEntry->CurrentColumn + gOptionBlockWidth - 1,\r
- MenuRefreshEntry->CurrentRow,\r
- MenuRefreshEntry->CurrentRow,\r
- PcdGet8 (PcdBrowserFieldTextColor) | FIELD_BACKGROUND\r
- );\r
- }\r
-\r
- gST->ConOut->SetAttribute (gST->ConOut, MenuRefreshEntry->CurrentAttribute);\r
- ProcessStringForDateTime(MenuRefreshEntry->MenuOption, OptionString, FALSE);\r
- PrintStringAt (MenuRefreshEntry->CurrentColumn, MenuRefreshEntry->CurrentRow, OptionString);\r
- FreePool (OptionString);\r
- }\r
-\r
- //\r
- // Question value may be changed, need invoke its Callback()\r
- //\r
- Status = ProcessCallBackFunction (Selection, Question, EFI_BROWSER_ACTION_CHANGING, FALSE);\r
-\r
- return Status;\r
-}\r
-\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
-RefreshQuestionNotify(\r
- IN EFI_EVENT Event,\r
- IN VOID *Context\r
- )\r
-{\r
- MENU_REFRESH_ENTRY *MenuRefreshEntry;\r
- UI_MENU_SELECTION *Selection;\r
-\r
- //\r
- // Reset FormPackage update flag\r
- //\r
- mHiiPackageListUpdated = FALSE;\r
-\r
- MenuRefreshEntry = (MENU_REFRESH_ENTRY *)Context;\r
- ASSERT (MenuRefreshEntry != NULL);\r
- Selection = MenuRefreshEntry->Selection;\r
-\r
- RefreshQuestion (MenuRefreshEntry);\r
- \r
- if (mHiiPackageListUpdated) {\r
- //\r
- // Package list is updated, force to reparse IFR binary of target Formset\r
- //\r
- mHiiPackageListUpdated = FALSE;\r
- Selection->Action = UI_ACTION_REFRESH_FORMSET;\r
- } \r
-}\r
-\r
-\r
-/**\r
- Refresh screen.\r
-\r
-**/\r
-EFI_STATUS\r
-RefreshForm (\r
- VOID\r
- )\r
-{\r
- MENU_REFRESH_ENTRY *MenuRefreshEntry;\r
- EFI_STATUS Status;\r
- UI_MENU_SELECTION *Selection;\r
-\r
- if (gMenuRefreshHead != NULL) {\r
- //\r
- // call from refresh interval process.\r
- //\r
- MenuRefreshEntry = gMenuRefreshHead;\r
- Selection = MenuRefreshEntry->Selection;\r
- //\r
- // Reset FormPackage update flag\r
- //\r
- mHiiPackageListUpdated = FALSE;\r
-\r
- do {\r
- Status = RefreshQuestion (MenuRefreshEntry);\r
- if (EFI_ERROR (Status)) {\r
- return Status;\r
- }\r
-\r
- MenuRefreshEntry = MenuRefreshEntry->Next;\r
-\r
- } while (MenuRefreshEntry != NULL);\r
-\r
- if (mHiiPackageListUpdated) {\r
- //\r
- // Package list is updated, force to reparse IFR binary of target Formset\r
- //\r
- mHiiPackageListUpdated = FALSE;\r
- Selection->Action = UI_ACTION_REFRESH_FORMSET;\r
- return EFI_SUCCESS;\r
- }\r
- }\r
-\r
- return EFI_TIMEOUT;\r
-}\r
-\r
-\r
-/**\r
- Wait for a given event to fire, or for an optional timeout to expire.\r
-\r
- @param Event The event to wait for\r
- @param Timeout An optional timeout value in 100 ns units.\r
- @param RefreshInterval Menu refresh interval (in seconds).\r
-\r
- @retval EFI_SUCCESS Event fired before Timeout expired.\r
- @retval EFI_TIME_OUT Timout expired before Event fired.\r
-\r
-**/\r
-EFI_STATUS\r
-UiWaitForSingleEvent (\r
- IN EFI_EVENT Event,\r
- IN UINT64 Timeout, OPTIONAL\r
- IN UINT8 RefreshInterval OPTIONAL\r
- )\r
-{\r
- EFI_STATUS Status;\r
- UINTN Index;\r
- EFI_EVENT TimerEvent;\r
- EFI_EVENT WaitList[2];\r
-\r
- if (Timeout != 0) {\r
- //\r
- // Create a timer event\r
- //\r
- Status = gBS->CreateEvent (EVT_TIMER, 0, NULL, NULL, &TimerEvent);\r
- if (!EFI_ERROR (Status)) {\r
- //\r
- // Set the timer event\r
- //\r
- gBS->SetTimer (\r
- TimerEvent,\r
- TimerRelative,\r
- Timeout\r
- );\r
-\r
- //\r
- // Wait for the original event or the timer\r
- //\r
- WaitList[0] = Event;\r
- WaitList[1] = TimerEvent;\r
- Status = gBS->WaitForEvent (2, WaitList, &Index);\r
- gBS->CloseEvent (TimerEvent);\r
-\r
- //\r
- // If the timer expired, change the return to timed out\r
- //\r
- if (!EFI_ERROR (Status) && Index == 1) {\r
- Status = EFI_TIMEOUT;\r
- }\r
- }\r
- } else {\r
- //\r
- // Update screen every second\r
- //\r
- if (RefreshInterval == 0) {\r
- Timeout = ONE_SECOND;\r
- } else {\r
- Timeout = RefreshInterval * ONE_SECOND;\r
- }\r
-\r
- do {\r
- Status = gBS->CreateEvent (EVT_TIMER, 0, NULL, NULL, &TimerEvent);\r
-\r
- //\r
- // Set the timer event\r
- //\r
- gBS->SetTimer (\r
- TimerEvent,\r
- TimerRelative,\r
- Timeout\r
- );\r
-\r
- //\r
- // Wait for the original event or the timer\r
- //\r
- WaitList[0] = Event;\r
- WaitList[1] = TimerEvent;\r
- Status = gBS->WaitForEvent (2, WaitList, &Index);\r
-\r
- //\r
- // If the timer expired, update anything that needs a refresh and keep waiting\r
- //\r
- if (!EFI_ERROR (Status) && Index == 1) {\r
- Status = EFI_TIMEOUT;\r
- if (RefreshInterval != 0) {\r
- Status = RefreshForm ();\r
- }\r
- }\r
-\r
- gBS->CloseEvent (TimerEvent);\r
- } while (Status == EFI_TIMEOUT);\r
- }\r
-\r
- return Status;\r
-}\r
-\r
-\r
-/**\r
- Add one menu option by specified description and context.\r
-\r
- @param String String description for this option.\r
- @param Handle Hii handle for the package list.\r
- @param Form The form this statement belong to.\r
- @param Statement Statement of this Menu Option.\r
- @param NumberOfLines Display lines for this Menu Option.\r
- @param MenuItemCount The index for this Option in the Menu.\r
-\r
- @retval Pointer Pointer to the added Menu Option.\r
-\r
-**/\r
-UI_MENU_OPTION *\r
-UiAddMenuOption (\r
- IN CHAR16 *String,\r
- IN EFI_HII_HANDLE Handle,\r
- IN FORM_BROWSER_FORM *Form,\r
- IN FORM_BROWSER_STATEMENT *Statement,\r
- IN UINT16 NumberOfLines,\r
- IN UINT16 MenuItemCount\r
- )\r
-{\r
- UI_MENU_OPTION *MenuOption;\r
- UINTN Index;\r
- UINTN Count;\r
-\r
- Count = 1;\r
- MenuOption = NULL;\r
-\r
- if (Statement->Operand == EFI_IFR_DATE_OP || Statement->Operand == EFI_IFR_TIME_OP) {\r
- //\r
- // Add three MenuOptions for Date/Time\r
- // Data format : [01/02/2004] [11:22:33]\r
- // Line number : 0 0 1 0 0 1\r
- //\r
- NumberOfLines = 0;\r
- Count = 3;\r
-\r
- if (Statement->Storage == NULL) {\r
- //\r
- // For RTC type of date/time, set default refresh interval to be 1 second\r
- //\r
- if (Statement->RefreshInterval == 0) {\r
- Statement->RefreshInterval = 1;\r
- }\r
- }\r
- }\r
-\r
- for (Index = 0; Index < Count; Index++) {\r
- MenuOption = AllocateZeroPool (sizeof (UI_MENU_OPTION));\r
- ASSERT (MenuOption);\r
-\r
- MenuOption->Signature = UI_MENU_OPTION_SIGNATURE;\r
- MenuOption->Description = String;\r
- MenuOption->Handle = Handle;\r
- MenuOption->ThisTag = Statement;\r
- MenuOption->EntryNumber = MenuItemCount;\r
-\r
- if (Index == 2) {\r
- //\r
- // Override LineNumber for the MenuOption in Date/Time sequence\r
- //\r
- MenuOption->Skip = 1;\r
- } else {\r
- MenuOption->Skip = NumberOfLines;\r
- }\r
- MenuOption->Sequence = Index;\r
-\r
- if (EvaluateExpressionList(Statement->Expression, FALSE, NULL, NULL) == ExpressGrayOut ) {\r
- MenuOption->GrayOut = TRUE;\r
- } else {\r
- MenuOption->GrayOut = FALSE;\r
- }\r
-\r
- //\r
- // If the form or the question has the lock attribute, deal same as grayout.\r
- //\r
- if (Form->Locked || Statement->Locked) {\r
- MenuOption->GrayOut = TRUE;\r
- }\r
- \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
- case EFI_IFR_CHECKBOX_OP:\r
- case EFI_IFR_PASSWORD_OP:\r
- case EFI_IFR_STRING_OP:\r
- //\r
- // User could change the value of these items\r
- //\r
- MenuOption->IsQuestion = TRUE;\r
- break;\r
-\r
- case EFI_IFR_TEXT_OP:\r
- if (FeaturePcdGet (PcdBrowserGrayOutTextStatement)) {\r
- //\r
- // Initializing GrayOut option as TRUE for Text setup options \r
- // so that those options will be Gray in colour and un selectable.\r
- //\r
- MenuOption->GrayOut = TRUE;\r
- }\r
- //\r
- // break skipped on purpose\r
- //\r
- default:\r
- MenuOption->IsQuestion = FALSE;\r
- break;\r
- }\r
-\r
- if ((Statement->ValueExpression != NULL) ||\r
- ((Statement->QuestionFlags & EFI_IFR_FLAG_READ_ONLY) != 0)) {\r
- MenuOption->ReadOnly = TRUE;\r
- if (FeaturePcdGet (PcdBrowerGrayOutReadOnlyMenu)) {\r
- MenuOption->GrayOut = TRUE;\r
- }\r
- }\r
-\r
- InsertTailList (&gMenuOption, &MenuOption->Link);\r
- }\r
-\r
- return MenuOption;\r
-}\r
-\r
-\r
-/**\r
- Routine used to abstract a generic dialog interface and return the selected key or string\r
-\r
- @param NumberOfLines The number of lines for the dialog box\r
- @param HotKey Defines whether a single character is parsed\r
- (TRUE) and returned in KeyValue or a string is\r
- returned in StringBuffer. Two special characters\r
- are considered when entering a string, a SCAN_ESC\r
- and an CHAR_CARRIAGE_RETURN. SCAN_ESC terminates\r
- string input and returns\r
- @param MaximumStringSize The maximum size in bytes of a typed in string\r
- (each character is a CHAR16) and the minimum\r
- string returned is two bytes\r
- @param StringBuffer The passed in pointer to the buffer which will\r
- hold the typed in string if HotKey is FALSE\r
- @param KeyValue The EFI_KEY value returned if HotKey is TRUE..\r
- @param ... A series of (quantity == NumberOfLines) text\r
- strings which will be used to construct the dialog\r
- box\r
-\r
- @retval EFI_SUCCESS Displayed dialog and received user interaction\r
- @retval EFI_INVALID_PARAMETER One of the parameters was invalid (e.g.\r
- (StringBuffer == NULL) && (HotKey == FALSE))\r
- @retval EFI_DEVICE_ERROR User typed in an ESC character to exit the routine\r
-\r
-**/\r
-EFI_STATUS\r
-EFIAPI\r
-CreateDialog (\r
- IN UINTN NumberOfLines,\r
- IN BOOLEAN HotKey,\r
- IN UINTN MaximumStringSize,\r
- OUT CHAR16 *StringBuffer,\r
- OUT EFI_INPUT_KEY *KeyValue,\r
- ...\r
- )\r
-{\r
- VA_LIST Marker;\r
- UINTN Count;\r
- EFI_INPUT_KEY Key;\r
- UINTN LargestString;\r
- CHAR16 *TempString;\r
- CHAR16 *BufferedString;\r
- CHAR16 *StackString;\r
- CHAR16 KeyPad[2];\r
- UINTN Start;\r
- UINTN Top;\r
- UINTN Index;\r
- EFI_STATUS Status;\r
- BOOLEAN SelectionComplete;\r
- UINTN InputOffset;\r
- UINTN CurrentAttribute;\r
- UINTN DimensionsWidth;\r
- UINTN DimensionsHeight;\r
-\r
- DimensionsWidth = gScreenDimensions.RightColumn - gScreenDimensions.LeftColumn;\r
- DimensionsHeight = gScreenDimensions.BottomRow - gScreenDimensions.TopRow;\r
-\r
- SelectionComplete = FALSE;\r
- InputOffset = 0;\r
- TempString = AllocateZeroPool (MaximumStringSize * 2);\r
- BufferedString = AllocateZeroPool (MaximumStringSize * 2);\r
- CurrentAttribute = gST->ConOut->Mode->Attribute;\r
-\r
- ASSERT (TempString);\r
- ASSERT (BufferedString);\r
-\r
- //\r
- // Zero the outgoing buffer\r
- //\r
- ZeroMem (StringBuffer, MaximumStringSize);\r
-\r
- if (HotKey) {\r
- if (KeyValue == NULL) {\r
- return EFI_INVALID_PARAMETER;\r
- }\r
- } else {\r
- if (StringBuffer == NULL) {\r
- return EFI_INVALID_PARAMETER;\r
- }\r
- }\r
- //\r
- // Disable cursor\r
- //\r
- gST->ConOut->EnableCursor (gST->ConOut, FALSE);\r
-\r
- LargestString = 0;\r
-\r
- VA_START (Marker, KeyValue);\r
-\r
- //\r
- // Determine the largest string in the dialog box\r
- // Notice we are starting with 1 since String is the first string\r
- //\r
- for (Count = 0; Count < NumberOfLines; Count++) {\r
- StackString = VA_ARG (Marker, CHAR16 *);\r
-\r
- if (StackString[0] == L' ') {\r
- InputOffset = Count + 1;\r
- }\r
-\r
- if ((GetStringWidth (StackString) / 2) > LargestString) {\r
- //\r
- // Size of the string visually and subtract the width by one for the null-terminator\r
- //\r
- LargestString = (GetStringWidth (StackString) / 2);\r
- }\r
- }\r
- VA_END (Marker);\r
-\r
- Start = (DimensionsWidth - LargestString - 2) / 2 + gScreenDimensions.LeftColumn + 1;\r
- Top = ((DimensionsHeight - NumberOfLines - 2) / 2) + gScreenDimensions.TopRow - 1;\r
-\r
- Count = 0;\r
-\r
- //\r
- // Display the Popup\r
- //\r
- VA_START (Marker, KeyValue);\r
- CreateSharedPopUp (LargestString, NumberOfLines, Marker);\r
- VA_END (Marker);\r
-\r
- //\r
- // Take the first key typed and report it back?\r
- //\r
- if (HotKey) {\r
- Status = WaitForKeyStroke (&Key);\r
- ASSERT_EFI_ERROR (Status);\r
- CopyMem (KeyValue, &Key, sizeof (EFI_INPUT_KEY));\r
-\r
- } else {\r
- do {\r
- Status = WaitForKeyStroke (&Key);\r
-\r
- switch (Key.UnicodeChar) {\r
- case CHAR_NULL:\r
- switch (Key.ScanCode) {\r
- case SCAN_ESC:\r
- FreePool (TempString);\r
- FreePool (BufferedString);\r
- gST->ConOut->SetAttribute (gST->ConOut, CurrentAttribute);\r
- gST->ConOut->EnableCursor (gST->ConOut, TRUE);\r
- return EFI_DEVICE_ERROR;\r
-\r
- default:\r
- break;\r
- }\r
-\r
- break;\r
-\r
- case CHAR_CARRIAGE_RETURN:\r
- SelectionComplete = TRUE;\r
- FreePool (TempString);\r
- FreePool (BufferedString);\r
- gST->ConOut->SetAttribute (gST->ConOut, CurrentAttribute);\r
- gST->ConOut->EnableCursor (gST->ConOut, TRUE);\r
- return EFI_SUCCESS;\r
- break;\r
-\r
- case CHAR_BACKSPACE:\r
- if (StringBuffer[0] != CHAR_NULL) {\r
- for (Index = 0; StringBuffer[Index] != CHAR_NULL; Index++) {\r
- TempString[Index] = StringBuffer[Index];\r
- }\r
- //\r
- // Effectively truncate string by 1 character\r
- //\r
- TempString[Index - 1] = CHAR_NULL;\r
- StrCpy (StringBuffer, TempString);\r
- }\r
- //\r
- // break skipped on purpose\r
- //\r
-\r
- default:\r
- //\r
- // If it is the beginning of the string, don't worry about checking maximum limits\r
- //\r
- if ((StringBuffer[0] == CHAR_NULL) && (Key.UnicodeChar != CHAR_BACKSPACE)) {\r
- StrnCpy (StringBuffer, &Key.UnicodeChar, 1);\r
- StrnCpy (TempString, &Key.UnicodeChar, 1);\r
- } else if ((GetStringWidth (StringBuffer) < MaximumStringSize) && (Key.UnicodeChar != CHAR_BACKSPACE)) {\r
- KeyPad[0] = Key.UnicodeChar;\r
- KeyPad[1] = CHAR_NULL;\r
- StrCat (StringBuffer, KeyPad);\r
- StrCat (TempString, KeyPad);\r
- }\r
- //\r
- // If the width of the input string is now larger than the screen, we nee to\r
- // adjust the index to start printing portions of the string\r
- //\r
- SetUnicodeMem (BufferedString, LargestString, L' ');\r
-\r
- PrintStringAt (Start + 1, Top + InputOffset, BufferedString);\r
-\r
- if ((GetStringWidth (StringBuffer) / 2) > (DimensionsWidth - 2)) {\r
- Index = (GetStringWidth (StringBuffer) / 2) - DimensionsWidth + 2;\r
- } else {\r
- Index = 0;\r
- }\r
-\r
- for (Count = 0; Index + 1 < GetStringWidth (StringBuffer) / 2; Index++, Count++) {\r
- BufferedString[Count] = StringBuffer[Index];\r
- }\r
-\r
- PrintStringAt (Start + 1, Top + InputOffset, BufferedString);\r
- break;\r
- }\r
- } while (!SelectionComplete);\r
- }\r
-\r
- gST->ConOut->SetAttribute (gST->ConOut, CurrentAttribute);\r
- gST->ConOut->EnableCursor (gST->ConOut, TRUE);\r
- return EFI_SUCCESS;\r
-}\r
-\r
-/**\r
- Draw a pop up windows based on the dimension, number of lines and\r
- strings specified.\r
-\r
- @param RequestedWidth The width of the pop-up.\r
- @param NumberOfLines The number of lines.\r
- @param Marker The variable argument list for the list of string to be printed.\r
-\r
-**/\r
-VOID\r
-CreateSharedPopUp (\r
- IN UINTN RequestedWidth,\r
- IN UINTN NumberOfLines,\r
- IN VA_LIST Marker\r
- )\r
-{\r
- UINTN Index;\r
- UINTN Count;\r
- CHAR16 Character;\r
- UINTN Start;\r
- UINTN End;\r
- UINTN Top;\r
- UINTN Bottom;\r
- CHAR16 *String;\r
- UINTN DimensionsWidth;\r
- UINTN DimensionsHeight;\r
-\r
- DimensionsWidth = gScreenDimensions.RightColumn - gScreenDimensions.LeftColumn;\r
- DimensionsHeight = gScreenDimensions.BottomRow - gScreenDimensions.TopRow;\r
-\r
- gST->ConOut->SetAttribute (gST->ConOut, POPUP_TEXT | POPUP_BACKGROUND);\r
-\r
- if ((RequestedWidth + 2) > DimensionsWidth) {\r
- RequestedWidth = DimensionsWidth - 2;\r
- }\r
-\r
- //\r
- // Subtract the PopUp width from total Columns, allow for one space extra on\r
- // each end plus a border.\r
- //\r
- Start = (DimensionsWidth - RequestedWidth - 2) / 2 + gScreenDimensions.LeftColumn + 1;\r
- End = Start + RequestedWidth + 1;\r
-\r
- Top = ((DimensionsHeight - NumberOfLines - 2) / 2) + gScreenDimensions.TopRow - 1;\r
- Bottom = Top + NumberOfLines + 2;\r
-\r
- Character = BOXDRAW_DOWN_RIGHT;\r
- PrintCharAt (Start, Top, Character);\r
- Character = BOXDRAW_HORIZONTAL;\r
- for (Index = Start; Index + 2 < End; Index++) {\r
- PrintChar (Character);\r
- }\r
-\r
- Character = BOXDRAW_DOWN_LEFT;\r
- PrintChar (Character);\r
- Character = BOXDRAW_VERTICAL;\r
-\r
- Count = 0;\r
- for (Index = Top; Index + 2 < Bottom; Index++, Count++) {\r
- String = VA_ARG (Marker, CHAR16*);\r
-\r
- //\r
- // This will clear the background of the line - we never know who might have been\r
- // here before us. This differs from the next clear in that it used the non-reverse\r
- // video for normal printing.\r
- //\r
- if (GetStringWidth (String) / 2 > 1) {\r
- ClearLines (Start, End, Index + 1, Index + 1, POPUP_TEXT | POPUP_BACKGROUND);\r
- }\r
-\r
- //\r
- // Passing in a space results in the assumption that this is where typing will occur\r
- //\r
- if (String[0] == L' ') {\r
- ClearLines (Start + 1, End - 1, Index + 1, Index + 1, POPUP_INVERSE_TEXT | POPUP_INVERSE_BACKGROUND);\r
- }\r
-\r
- //\r
- // Passing in a NULL results in a blank space\r
- //\r
- if (String[0] == CHAR_NULL) {\r
- ClearLines (Start, End, Index + 1, Index + 1, POPUP_TEXT | POPUP_BACKGROUND);\r
- }\r
-\r
- PrintStringAt (\r
- ((DimensionsWidth - GetStringWidth (String) / 2) / 2) + gScreenDimensions.LeftColumn + 1,\r
- Index + 1,\r
- String\r
- );\r
- gST->ConOut->SetAttribute (gST->ConOut, POPUP_TEXT | POPUP_BACKGROUND);\r
- PrintCharAt (Start, Index + 1, Character);\r
- PrintCharAt (End - 1, Index + 1, Character);\r
- }\r
-\r
- Character = BOXDRAW_UP_RIGHT;\r
- PrintCharAt (Start, Bottom - 1, Character);\r
- Character = BOXDRAW_HORIZONTAL;\r
- for (Index = Start; Index + 2 < End; Index++) {\r
- PrintChar (Character);\r
- }\r
-\r
- Character = BOXDRAW_UP_LEFT;\r
- PrintChar (Character);\r
-}\r
-\r
-/**\r
- Draw a pop up windows based on the dimension, number of lines and\r
- strings specified.\r
-\r
- @param RequestedWidth The width of the pop-up.\r
- @param NumberOfLines The number of lines.\r
- @param ... A series of text strings that displayed in the pop-up.\r
-\r
-**/\r
-VOID\r
-EFIAPI\r
-CreateMultiStringPopUp (\r
- IN UINTN RequestedWidth,\r
- IN UINTN NumberOfLines,\r
- ...\r
- )\r
-{\r
- VA_LIST Marker;\r
-\r
- VA_START (Marker, NumberOfLines);\r
-\r
- CreateSharedPopUp (RequestedWidth, NumberOfLines, Marker);\r
-\r
- VA_END (Marker);\r
-}\r
-\r
-\r
-/**\r
- Update status bar on the bottom of menu.\r
-\r
- @param Selection Current Selction info.\r
- @param MessageType The type of message to be shown.\r
- @param Flags The flags in Question header.\r
- @param State Set or clear.\r
-\r
-**/\r
-VOID\r
-UpdateStatusBar (\r
- IN UI_MENU_SELECTION *Selection,\r
- IN UINTN MessageType,\r
- IN UINT8 Flags,\r
- IN BOOLEAN State\r
- )\r
-{\r
- UINTN Index;\r
- CHAR16 *NvUpdateMessage;\r
- CHAR16 *InputErrorMessage;\r
- LIST_ENTRY *Link;\r
- FORM_BROWSER_FORMSET *LocalFormSet;\r
- FORM_BROWSER_STATEMENT *Question;\r
- \r
- NvUpdateMessage = GetToken (STRING_TOKEN (NV_UPDATE_MESSAGE), gHiiHandle);\r
- InputErrorMessage = GetToken (STRING_TOKEN (INPUT_ERROR_MESSAGE), gHiiHandle);\r
-\r
- switch (MessageType) {\r
- case INPUT_ERROR:\r
- if (State) {\r
- gST->ConOut->SetAttribute (gST->ConOut, ERROR_TEXT);\r
- PrintStringAt (\r
- gScreenDimensions.LeftColumn + gPromptBlockWidth,\r
- gScreenDimensions.BottomRow - 1,\r
- InputErrorMessage\r
- );\r
- mInputError = TRUE;\r
- } else {\r
- gST->ConOut->SetAttribute (gST->ConOut, PcdGet8 (PcdBrowserFieldTextHighlightColor));\r
- for (Index = 0; Index < (GetStringWidth (InputErrorMessage) - 2) / 2; Index++) {\r
- PrintAt (gScreenDimensions.LeftColumn + gPromptBlockWidth + Index, gScreenDimensions.BottomRow - 1, L" ");\r
- }\r
-\r
- mInputError = FALSE;\r
- }\r
- break;\r
-\r
- case NV_UPDATE_REQUIRED:\r
- //\r
- // Global setting support. Show configuration change on every form.\r
- //\r
- if (State) {\r
- gResetRequired = (BOOLEAN) (gResetRequired | ((Flags & EFI_IFR_FLAG_RESET_REQUIRED) == EFI_IFR_FLAG_RESET_REQUIRED));\r
-\r
- if (Selection != NULL && Selection->Statement != NULL) {\r
- Question = Selection->Statement;\r
- if (Question->Storage != NULL || Question->Operand == EFI_IFR_DATE_OP || Question->Operand == EFI_IFR_TIME_OP) {\r
- //\r
- // Update only for Question value that need to be saved into Storage.\r
- //\r
- Selection->Form->NvUpdateRequired = TRUE;\r
- }\r
- }\r
- \r
- if (Selection == NULL || IsNvUpdateRequired (Selection->FormSet)) {\r
- gST->ConOut->SetAttribute (gST->ConOut, INFO_TEXT);\r
- PrintStringAt (\r
- gScreenDimensions.LeftColumn + gPromptBlockWidth + gOptionBlockWidth,\r
- gScreenDimensions.BottomRow - 1,\r
- NvUpdateMessage\r
- );\r
- }\r
- } else {\r
- gST->ConOut->SetAttribute (gST->ConOut, PcdGet8 (PcdBrowserFieldTextHighlightColor));\r
- for (Index = 0; Index < (GetStringWidth (NvUpdateMessage) - 2) / 2; Index++) {\r
- PrintAt (\r
- (gScreenDimensions.LeftColumn + gPromptBlockWidth + gOptionBlockWidth + Index),\r
- gScreenDimensions.BottomRow - 1,\r
- L" "\r
- );\r
- }\r
- }\r
- break;\r
-\r
- case REFRESH_STATUS_BAR:\r
- if (mInputError) {\r
- UpdateStatusBar (Selection, INPUT_ERROR, Flags, TRUE);\r
- }\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 (IsNvUpdateRequired(LocalFormSet)) {\r
- UpdateStatusBar (NULL, NV_UPDATE_REQUIRED, Flags, TRUE);\r
- break;\r
- }\r
- Link = GetNextNode (&gBrowserFormSetList, Link);\r
- }\r
- break;\r
- case FormSetLevel:\r
- case FormLevel:\r
- UpdateStatusBar (Selection, NV_UPDATE_REQUIRED, Flags, TRUE);\r
- default:\r
- break;\r
- }\r
-\r
- break;\r
-\r
- default:\r
- break;\r
- }\r
-\r
- FreePool (InputErrorMessage);\r
- FreePool (NvUpdateMessage);\r
- return ;\r
-}\r
-\r
-\r
-/**\r
- Get the supported width for a particular op-code\r
-\r
- @param Statement The FORM_BROWSER_STATEMENT structure passed in.\r
- @param Handle The handle in the HII database being used\r
-\r
- @return Returns the number of CHAR16 characters that is support.\r
-\r
-**/\r
-UINT16\r
-GetWidth (\r
- IN FORM_BROWSER_STATEMENT *Statement,\r
- IN EFI_HII_HANDLE Handle\r
- )\r
-{\r
- CHAR16 *String;\r
- UINTN Size;\r
- UINT16 Width;\r
-\r
- Size = 0;\r
-\r
- //\r
- // See if the second text parameter is really NULL\r
- //\r
- if ((Statement->Operand == EFI_IFR_TEXT_OP) && (Statement->TextTwo != 0)) {\r
- String = GetToken (Statement->TextTwo, Handle);\r
- Size = StrLen (String);\r
- FreePool (String);\r
- }\r
-\r
- if ((Statement->Operand == EFI_IFR_SUBTITLE_OP) ||\r
- (Statement->Operand == EFI_IFR_REF_OP) ||\r
- (Statement->Operand == EFI_IFR_PASSWORD_OP) ||\r
- (Statement->Operand == EFI_IFR_ACTION_OP) ||\r
- (Statement->Operand == EFI_IFR_RESET_BUTTON_OP) ||\r
- //\r
- // Allow a wide display if text op-code and no secondary text op-code\r
- //\r
- ((Statement->Operand == EFI_IFR_TEXT_OP) && (Size == 0))\r
- ) {\r
- Width = (UINT16) (gPromptBlockWidth + gOptionBlockWidth);\r
- } else {\r
- Width = (UINT16) gPromptBlockWidth;\r
- }\r
-\r
- if (Statement->InSubtitle) {\r
- Width -= SUBTITLE_INDENT;\r
- }\r
-\r
- return (UINT16) (Width - LEFT_SKIPPED_COLUMNS);\r
-}\r
-\r
-/**\r
- Will copy LineWidth amount of a string in the OutputString buffer and return the\r
- number of CHAR16 characters that were copied into the OutputString buffer.\r
- The output string format is:\r
- Glyph Info + String info + '\0'.\r
-\r
- In the code, it deals \r,\n,\r\n same as \n\r, also it not process the \r or \g.\r
-\r
- @param InputString String description for this option.\r
- @param LineWidth Width of the desired string to extract in CHAR16\r
- characters\r
- @param GlyphWidth The glyph width of the begin of the char in the string.\r
- @param Index Where in InputString to start the copy process\r
- @param OutputString Buffer to copy the string into\r
-\r
- @return Returns the number of CHAR16 characters that were copied into the OutputString \r
- buffer, include extra glyph info and '\0' info.\r
-\r
-**/\r
-UINT16\r
-GetLineByWidth (\r
- IN CHAR16 *InputString,\r
- IN UINT16 LineWidth,\r
- IN OUT UINT16 *GlyphWidth,\r
- IN OUT UINTN *Index,\r
- OUT CHAR16 **OutputString\r
- )\r
-{\r
- UINT16 StrOffset;\r
- UINT16 GlyphOffset;\r
- UINT16 OriginalGlyphWidth;\r
- BOOLEAN ReturnFlag;\r
- UINT16 LastSpaceOffset;\r
- UINT16 LastGlyphWidth;\r
-\r
- if (InputString == NULL || Index == NULL || OutputString == NULL) {\r
- return 0;\r
- }\r
-\r
- if (LineWidth == 0 || *GlyphWidth == 0) {\r
- return 0;\r
- }\r
-\r
- //\r
- // Save original glyph width.\r
- //\r
- OriginalGlyphWidth = *GlyphWidth;\r
- LastGlyphWidth = OriginalGlyphWidth;\r
- ReturnFlag = FALSE;\r
- LastSpaceOffset = 0;\r
-\r
- //\r
- // NARROW_CHAR can not be printed in screen, so if a line only contain the two CHARs: 'NARROW_CHAR + CHAR_CARRIAGE_RETURN' , it is a empty line in Screen.\r
- // To avoid displaying this empty line in screen, just skip the two CHARs here.\r
- //\r
- if ((InputString[*Index] == NARROW_CHAR) && (InputString[*Index + 1] == CHAR_CARRIAGE_RETURN)) {\r
- *Index = *Index + 2;\r
- }\r
-\r
- //\r
- // Fast-forward the string and see if there is a carriage-return in the string\r
- //\r
- for (StrOffset = 0, GlyphOffset = 0; GlyphOffset <= LineWidth; StrOffset++) {\r
- switch (InputString[*Index + StrOffset]) {\r
- case NARROW_CHAR:\r
- *GlyphWidth = 1;\r
- break;\r
-\r
- case WIDE_CHAR:\r
- *GlyphWidth = 2;\r
- break;\r
-\r
- case CHAR_CARRIAGE_RETURN:\r
- case CHAR_LINEFEED:\r
- case CHAR_NULL:\r
- ReturnFlag = TRUE;\r
- break;\r
-\r
- default:\r
- GlyphOffset = GlyphOffset + *GlyphWidth;\r
-\r
- //\r
- // Record the last space info in this line. Will be used in rewind.\r
- //\r
- if ((InputString[*Index + StrOffset] == CHAR_SPACE) && (GlyphOffset <= LineWidth)) {\r
- LastSpaceOffset = StrOffset;\r
- LastGlyphWidth = *GlyphWidth;\r
- }\r
- break;\r
- }\r
-\r
- if (ReturnFlag) {\r
- break;\r
- }\r
- } \r
-\r
- //\r
- // Rewind the string from the maximum size until we see a space to break the line\r
- //\r
- if (GlyphOffset > LineWidth) {\r
- //\r
- // Rewind the string to last space char in this line.\r
- //\r
- if (LastSpaceOffset != 0) {\r
- StrOffset = LastSpaceOffset;\r
- *GlyphWidth = LastGlyphWidth;\r
- } else {\r
- //\r
- // Roll back to last char in the line width.\r
- //\r
- StrOffset--;\r
- }\r
- }\r
-\r
- //\r
- // The CHAR_NULL has process last time, this time just return 0 to stand for the end.\r
- //\r
- if (StrOffset == 0 && (InputString[*Index + StrOffset] == CHAR_NULL)) {\r
- return 0;\r
- }\r
-\r
- //\r
- // Need extra glyph info and '\0' info, so +2.\r
- //\r
- *OutputString = AllocateZeroPool (((UINTN) (StrOffset + 2) * sizeof(CHAR16)));\r
- if (*OutputString == NULL) {\r
- return 0;\r
- }\r
-\r
- //\r
- // Save the glyph info at the begin of the string, will used by Print function.\r
- //\r
- if (OriginalGlyphWidth == 1) {\r
- *(*OutputString) = NARROW_CHAR;\r
- } else {\r
- *(*OutputString) = WIDE_CHAR;\r
- }\r
-\r
- CopyMem ((*OutputString) + 1, &InputString[*Index], StrOffset * sizeof(CHAR16));\r
-\r
- if (InputString[*Index + StrOffset] == CHAR_SPACE) {\r
- //\r
- // Skip the space info at the begin of next line.\r
- // \r
- *Index = (UINT16) (*Index + StrOffset + 1);\r
- } else if (InputString[*Index + StrOffset] == CHAR_LINEFEED) {\r
- //\r
- // Skip the /n or /n/r info.\r
- //\r
- if (InputString[*Index + StrOffset + 1] == CHAR_CARRIAGE_RETURN) {\r
- *Index = (UINT16) (*Index + StrOffset + 2);\r
- } else {\r
- *Index = (UINT16) (*Index + StrOffset + 1);\r
- }\r
- } else if (InputString[*Index + StrOffset] == CHAR_CARRIAGE_RETURN) {\r
- //\r
- // Skip the /r or /r/n info.\r
- // \r
- if (InputString[*Index + StrOffset + 1] == CHAR_LINEFEED) {\r
- *Index = (UINT16) (*Index + StrOffset + 2);\r
- } else {\r
- *Index = (UINT16) (*Index + StrOffset + 1);\r
- }\r
- } else {\r
- *Index = (UINT16) (*Index + StrOffset);\r
- }\r
-\r
- //\r
- // Include extra glyph info and '\0' info, so +2.\r
- //\r
- return StrOffset + 2;\r
-}\r
-\r
-\r
-/**\r
- Update display lines for a Menu Option.\r
-\r
- @param Selection The user's selection.\r
- @param MenuOption The MenuOption to be checked.\r
-\r
-**/\r
-VOID\r
-UpdateOptionSkipLines (\r
- IN UI_MENU_SELECTION *Selection,\r
- IN UI_MENU_OPTION *MenuOption\r
- )\r
-{\r
- UINTN Index;\r
- UINT16 Width;\r
- UINTN Row;\r
- UINTN OriginalRow;\r
- CHAR16 *OutputString;\r
- CHAR16 *OptionString;\r
- UINT16 GlyphWidth;\r
-\r
- Row = 0;\r
- OptionString = NULL;\r
- Width = (UINT16) gOptionBlockWidth;\r
- OriginalRow = 0;\r
- GlyphWidth = 1;\r
- \r
- ProcessOptions (Selection, MenuOption, FALSE, &OptionString);\r
- if (OptionString == NULL) {\r
- return;\r
- }\r
-\r
- for (Index = 0; GetLineByWidth (OptionString, Width, &GlyphWidth, &Index, &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 (&OptionString[Index]) != 0) {\r
- Row++;\r
- //\r
- // Since the Number of lines for this menu entry may or may not be reflected accurately\r
- // since the prompt might be 1 lines and option might be many, and vice versa, we need to do\r
- // some testing to ensure we are keeping this in-sync.\r
- //\r
- // If the difference in rows is greater than or equal to the skip value, increase the skip value\r
- //\r
- if ((Row - OriginalRow) >= MenuOption->Skip) {\r
- MenuOption->Skip++;\r
- }\r
- }\r
-\r
- FreePool (OutputString);\r
- }\r
-\r
- if (OptionString != NULL) {\r
- FreePool (OptionString);\r
- }\r
-}\r
-\r
-\r
-/**\r
- Check whether this Menu Option could be highlighted.\r
-\r
- This is an internal function.\r
-\r
- @param MenuOption The MenuOption to be checked.\r
-\r
- @retval TRUE This Menu Option is selectable.\r
- @retval FALSE This Menu Option could not be selected.\r
-\r
-**/\r
-BOOLEAN\r
-IsSelectable (\r
- UI_MENU_OPTION *MenuOption\r
- )\r
-{\r
- if ((MenuOption->ThisTag->Operand == EFI_IFR_SUBTITLE_OP) ||\r
- MenuOption->GrayOut || MenuOption->ReadOnly) {\r
- return FALSE;\r
- } else {\r
- return TRUE;\r
- }\r
-}\r
-\r
-\r
-/**\r
- Determine if the menu is the last menu that can be selected.\r
-\r
- This is an internal function.\r
-\r
- @param Direction The scroll direction. False is down. True is up.\r
- @param CurrentPos The current focus.\r
-\r
- @return FALSE -- the menu isn't the last menu that can be selected.\r
- @return TRUE -- the menu is the last menu that can be selected.\r
-\r
-**/\r
-BOOLEAN\r
-ValueIsScroll (\r
- IN BOOLEAN Direction,\r
- IN LIST_ENTRY *CurrentPos\r
- )\r
-{\r
- LIST_ENTRY *Temp;\r
-\r
- Temp = Direction ? CurrentPos->BackLink : CurrentPos->ForwardLink;\r
-\r
- if (Temp == &gMenuOption) {\r
- return TRUE;\r
- }\r
-\r
- return FALSE;\r
-}\r
-\r
-\r
-/**\r
- Move to next selectable statement.\r
-\r
- This is an internal function.\r
-\r
- @param Selection Menu selection.\r
- @param GoUp The navigation direction. TRUE: up, FALSE: down.\r
- @param CurrentPosition Current position.\r
- @param GapToTop Gap position to top or bottom.\r
-\r
- @return The row distance from current MenuOption to next selectable MenuOption.\r
-\r
- @retval -1 Reach the begin of the menu, still can't find the selectable menu.\r
- @retval Value Find the selectable menu, maybe the truly selectable, maybe the l\r
- last menu showing at current form.\r
-\r
-**/\r
-INTN\r
-MoveToNextStatement (\r
- IN UI_MENU_SELECTION *Selection,\r
- IN BOOLEAN GoUp,\r
- IN OUT LIST_ENTRY **CurrentPosition,\r
- IN UINTN GapToTop\r
- )\r
-{\r
- INTN Distance;\r
- LIST_ENTRY *Pos;\r
- UI_MENU_OPTION *NextMenuOption;\r
- UI_MENU_OPTION *PreMenuOption;\r
-\r
- Distance = 0;\r
- Pos = *CurrentPosition;\r
- PreMenuOption = MENU_OPTION_FROM_LINK (Pos);\r
-\r
- while (TRUE) {\r
- NextMenuOption = MENU_OPTION_FROM_LINK (Pos);\r
- //\r
- // NextMenuOption->Row == 0 means this menu has not calculate\r
- // the NextMenuOption->Skip value yet, just calculate here.\r
- //\r
- if (NextMenuOption->Row == 0) {\r
- UpdateOptionSkipLines (Selection, NextMenuOption);\r
- }\r
- \r
- if (GoUp && (PreMenuOption != NextMenuOption)) {\r
- //\r
- // In this case, still can't find the selectable menu,\r
- // return the last one in the showing form.\r
- //\r
- if ((UINTN) Distance + NextMenuOption->Skip > GapToTop) {\r
- NextMenuOption = PreMenuOption;\r
- break;\r
- }\r
-\r
- //\r
- // Current Position doesn't need to be caculated when go up.\r
- // Caculate distanct at first when go up\r
- // \r
- Distance += NextMenuOption->Skip;\r
- }\r
-\r
- if (IsSelectable (NextMenuOption)) {\r
- break;\r
- }\r
-\r
- //\r
- // Arrive at begin of the menu list.\r
- //\r
- if ((GoUp ? Pos->BackLink : Pos->ForwardLink) == &gMenuOption) {\r
- Distance = -1;\r
- break;\r
- }\r
-\r
- if (!GoUp) {\r
- //\r
- // In this case, still can't find the selectable menu,\r
- // return the last one in the showing form.\r
- //\r
- if ((UINTN) Distance + NextMenuOption->Skip > GapToTop) {\r
- NextMenuOption = PreMenuOption;\r
- break;\r
- }\r
-\r
- Distance += NextMenuOption->Skip;\r
- }\r
-\r
- PreMenuOption = NextMenuOption;\r
- Pos = (GoUp ? Pos->BackLink : Pos->ForwardLink);\r
- }\r
-\r
- *CurrentPosition = &NextMenuOption->Link;\r
- return Distance;\r
-}\r
-\r
-\r
-/**\r
- Adjust Data and Time position accordingly.\r
- Data format : [01/02/2004] [11:22:33]\r
- Line number : 0 0 1 0 0 1\r
-\r
- This is an internal function.\r
-\r
- @param DirectionUp the up or down direction. False is down. True is\r
- up.\r
- @param CurrentPosition Current position. On return: Point to the last\r
- Option (Year or Second) if up; Point to the first\r
- Option (Month or Hour) if down.\r
-\r
- @return Return line number to pad. It is possible that we stand on a zero-advance\r
- @return data or time opcode, so pad one line when we judge if we are going to scroll outside.\r
-\r
-**/\r
-UINTN\r
-AdjustDateAndTimePosition (\r
- IN BOOLEAN DirectionUp,\r
- IN OUT LIST_ENTRY **CurrentPosition\r
- )\r
-{\r
- UINTN Count;\r
- LIST_ENTRY *NewPosition;\r
- UI_MENU_OPTION *MenuOption;\r
- UINTN PadLineNumber;\r
-\r
- PadLineNumber = 0;\r
- NewPosition = *CurrentPosition;\r
- MenuOption = MENU_OPTION_FROM_LINK (NewPosition);\r
-\r
- if ((MenuOption->ThisTag->Operand == EFI_IFR_DATE_OP) ||\r
- (MenuOption->ThisTag->Operand == EFI_IFR_TIME_OP)) {\r
- //\r
- // Calculate the distance from current position to the last Date/Time MenuOption\r
- //\r
- Count = 0;\r
- while (MenuOption->Skip == 0) {\r
- Count++;\r
- NewPosition = NewPosition->ForwardLink;\r
- MenuOption = MENU_OPTION_FROM_LINK (NewPosition);\r
- PadLineNumber = 1;\r
- }\r
-\r
- NewPosition = *CurrentPosition;\r
- if (DirectionUp) {\r
- //\r
- // Since the behavior of hitting the up arrow on a Date/Time MenuOption is intended\r
- // to be one that back to the previous set of MenuOptions, we need to advance to the first\r
- // Date/Time MenuOption and leave the remaining logic in CfUiUp intact so the appropriate\r
- // checking can be done.\r
- //\r
- while (Count++ < 2) {\r
- NewPosition = NewPosition->BackLink;\r
- }\r
- } else {\r
- //\r
- // Since the behavior of hitting the down arrow on a Date/Time MenuOption is intended\r
- // to be one that progresses to the next set of MenuOptions, we need to advance to the last\r
- // Date/Time MenuOption and leave the remaining logic in CfUiDown intact so the appropriate\r
- // checking can be done.\r
- //\r
- while (Count-- > 0) {\r
- NewPosition = NewPosition->ForwardLink;\r
- }\r
- }\r
-\r
- *CurrentPosition = NewPosition;\r
- }\r
-\r
- return PadLineNumber;\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
- 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
- @param Repaint Whether need to repaint the menu.\r
- @param NewLine Whether need to create new line.\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
- OUT BOOLEAN *Repaint,\r
- OUT BOOLEAN *NewLine\r
- )\r
-{\r
- CHAR16 *StringPtr;\r
- EFI_DEVICE_PATH_PROTOCOL *DevicePath;\r
- FORM_BROWSER_FORM *RefForm;\r
- EFI_INPUT_KEY Key;\r
- EFI_STATUS Status;\r
-\r
- Status = EFI_SUCCESS;\r
- StringPtr = 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
- Selection->Handle = 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
- do {\r
- CreateDialog (4, TRUE, 0, NULL, &Key, gEmptyString, gProtocolNotFound, gPressEnter, gEmptyString);\r
- } while (Key.UnicodeChar != CHAR_CARRIAGE_RETURN);\r
- if (Repaint != NULL) {\r
- *Repaint = TRUE;\r
- }\r
- FreePool (StringPtr);\r
- return Status;\r
- }\r
-\r
- Selection->Action = UI_ACTION_REFRESH_FORMSET;\r
- if (Selection->Handle == NULL) {\r
- //\r
- // If target Hii Handle not found, exit\r
- //\r
- Selection->Action = UI_ACTION_EXIT;\r
- Selection->Statement = NULL;\r
- return Status;\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
- //\r
- // Goto another Formset, check for uncommitted data\r
- //\r
- Selection->Action = UI_ACTION_REFRESH_FORMSET;\r
- \r
- Selection->Handle = FormSetGuidToHiiHandle(&Statement->HiiValue.Value.ref.FormSetGuid);\r
- if (Selection->Handle == NULL) {\r
- //\r
- // If target Hii Handle not found, exit\r
- //\r
- Selection->Action = UI_ACTION_EXIT;\r
- Selection->Statement = NULL;\r
- return Status;\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
- // Check whether target From is suppressed.\r
- //\r
- RefForm = IdToForm (Selection->FormSet, Statement->HiiValue.Value.ref.FormId);\r
-\r
- if ((RefForm != NULL) && (RefForm->SuppressExpression != NULL)) {\r
- if (EvaluateExpressionList(RefForm->SuppressExpression, TRUE, Selection->FormSet, RefForm) != ExpressFalse) {\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
- if (Repaint != NULL) {\r
- *Repaint = TRUE;\r
- }\r
- return Status;\r
- }\r
- }\r
-\r
- //\r
- // Goto another form inside this formset,\r
- //\r
- Selection->Action = UI_ACTION_REFRESH_FORM;\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
- //\r
- // Goto another Question\r
- //\r
- Selection->QuestionId = Statement->HiiValue.Value.ref.QuestionId;\r
-\r
- if ((Statement->QuestionFlags & EFI_IFR_FLAG_CALLBACK) != 0) {\r
- Selection->Action = UI_ACTION_REFRESH_FORM;\r
- } else {\r
- if (Repaint != NULL) {\r
- *Repaint = TRUE;\r
- }\r
- if (NewLine != NULL) {\r
- *NewLine = TRUE;\r
- }\r
- }\r
- } else {\r
- if ((Statement->QuestionFlags & EFI_IFR_FLAG_CALLBACK) != 0) {\r
- Selection->Action = UI_ACTION_REFRESH_FORM;\r
- }\r
- }\r
-\r
- return Status;\r
-}\r
-\r
-/**\r
- Display menu and wait for user to select one menu option, then return it.\r
- If AutoBoot is enabled, then if user doesn't select any option,\r
- after period of time, it will automatically return the first menu option.\r
-\r
- @param Selection Menu selection.\r
-\r
- @retval EFI_SUCESSS This function always return successfully for now.\r
-\r
-**/\r
-EFI_STATUS\r
-UiDisplayMenu (\r
- IN OUT UI_MENU_SELECTION *Selection\r
- )\r
-{\r
- INTN SkipValue;\r
- INTN Difference;\r
- UINTN DistanceValue;\r
- UINTN Row;\r
- UINTN Col;\r
- UINTN Temp;\r
- UINTN Temp2;\r
- UINTN TopRow;\r
- UINTN BottomRow;\r
- UINTN OriginalRow;\r
- UINTN Index;\r
- UINT16 Width;\r
- CHAR16 *StringPtr;\r
- CHAR16 *OptionString;\r
- CHAR16 *OutputString;\r
- CHAR16 *HelpString;\r
- CHAR16 *HelpHeaderString;\r
- CHAR16 *HelpBottomString;\r
- BOOLEAN NewLine;\r
- BOOLEAN Repaint;\r
- BOOLEAN SavedValue;\r
- BOOLEAN UpArrow;\r
- BOOLEAN DownArrow;\r
- BOOLEAN InitializedFlag;\r
- EFI_STATUS Status;\r
- EFI_INPUT_KEY Key;\r
- LIST_ENTRY *Link;\r
- LIST_ENTRY *NewPos;\r
- LIST_ENTRY *TopOfScreen;\r
- LIST_ENTRY *SavedListEntry;\r
- UI_MENU_OPTION *MenuOption;\r
- UI_MENU_OPTION *NextMenuOption;\r
- UI_MENU_OPTION *SavedMenuOption;\r
- UI_MENU_OPTION *PreviousMenuOption;\r
- UI_CONTROL_FLAG ControlFlag;\r
- EFI_SCREEN_DESCRIPTOR LocalScreen;\r
- MENU_REFRESH_ENTRY *MenuRefreshEntry;\r
- MENU_REFRESH_ENTRY *MenuUpdateEntry; \r
- UI_SCREEN_OPERATION ScreenOperation;\r
- UINT8 MinRefreshInterval;\r
- UINT16 DefaultId;\r
- FORM_BROWSER_STATEMENT *Statement;\r
- UI_MENU_LIST *CurrentMenu;\r
- UINTN ModalSkipColumn;\r
- BROWSER_HOT_KEY *HotKey;\r
- UINTN HelpPageIndex;\r
- UINTN HelpPageCount;\r
- UINTN RowCount;\r
- UINTN HelpLine;\r
- UINTN HelpHeaderLine;\r
- UINTN HelpBottomLine;\r
- BOOLEAN MultiHelpPage;\r
- UINT16 GlyphWidth;\r
- UINT16 EachLineWidth;\r
- UINT16 HeaderLineWidth;\r
- UINT16 BottomLineWidth;\r
-\r
- CopyMem (&LocalScreen, &gScreenDimensions, sizeof (EFI_SCREEN_DESCRIPTOR));\r
-\r
- Status = EFI_SUCCESS;\r
- HelpString = NULL;\r
- HelpHeaderString = NULL;\r
- HelpBottomString = NULL;\r
- OptionString = NULL;\r
- ScreenOperation = UiNoOperation;\r
- NewLine = TRUE;\r
- MinRefreshInterval = 0;\r
- DefaultId = 0;\r
- HelpPageCount = 0;\r
- HelpLine = 0;\r
- RowCount = 0;\r
- HelpBottomLine = 0;\r
- HelpHeaderLine = 0;\r
- HelpPageIndex = 0;\r
- MultiHelpPage = FALSE;\r
- EachLineWidth = 0;\r
- HeaderLineWidth = 0;\r
- BottomLineWidth = 0;\r
- OutputString = NULL;\r
- UpArrow = FALSE;\r
- DownArrow = FALSE;\r
- SkipValue = 0;\r
- MenuRefreshEntry = gMenuRefreshHead;\r
-\r
- NextMenuOption = NULL;\r
- PreviousMenuOption = NULL;\r
- SavedMenuOption = NULL;\r
- HotKey = NULL;\r
- ModalSkipColumn = (LocalScreen.RightColumn - LocalScreen.LeftColumn) / 6;\r
-\r
- ZeroMem (&Key, sizeof (EFI_INPUT_KEY));\r
-\r
- if ((gClassOfVfr & FORMSET_CLASS_FRONT_PAGE) == FORMSET_CLASS_FRONT_PAGE){\r
- TopRow = LocalScreen.TopRow + FRONT_PAGE_HEADER_HEIGHT + SCROLL_ARROW_HEIGHT;\r
- Row = LocalScreen.TopRow + FRONT_PAGE_HEADER_HEIGHT + SCROLL_ARROW_HEIGHT;\r
- } else {\r
- TopRow = LocalScreen.TopRow + NONE_FRONT_PAGE_HEADER_HEIGHT + SCROLL_ARROW_HEIGHT;\r
- Row = LocalScreen.TopRow + NONE_FRONT_PAGE_HEADER_HEIGHT + SCROLL_ARROW_HEIGHT;\r
- }\r
-\r
- if (Selection->Form->ModalForm) {\r
- Col = LocalScreen.LeftColumn + LEFT_SKIPPED_COLUMNS + ModalSkipColumn;\r
- } else {\r
- Col = LocalScreen.LeftColumn + LEFT_SKIPPED_COLUMNS;\r
- }\r
-\r
- BottomRow = LocalScreen.BottomRow - STATUS_BAR_HEIGHT - gFooterHeight - SCROLL_ARROW_HEIGHT - 1;\r
-\r
- Selection->TopRow = TopRow;\r
- Selection->BottomRow = BottomRow;\r
- Selection->PromptCol = Col;\r
- Selection->OptionCol = gPromptBlockWidth + 1 + LocalScreen.LeftColumn;\r
- Selection->Statement = NULL;\r
-\r
- TopOfScreen = gMenuOption.ForwardLink;\r
- Repaint = TRUE;\r
- MenuOption = NULL;\r
-\r
- //\r
- // Find current Menu\r
- //\r
- CurrentMenu = UiFindMenuList (Selection->Handle, &Selection->FormSetGuid, Selection->FormId);\r
- if (CurrentMenu == NULL) {\r
- //\r
- // Current menu not found, add it to the menu tree\r
- //\r
- CurrentMenu = UiAddMenuList (Selection->CurrentMenu, Selection->Handle, &Selection->FormSetGuid, Selection->FormId);\r
- }\r
- ASSERT (CurrentMenu != NULL);\r
- Selection->CurrentMenu = CurrentMenu;\r
-\r
- if (Selection->QuestionId == 0) {\r
- //\r
- // Highlight not specified, fetch it from cached menu\r
- //\r
- Selection->QuestionId = CurrentMenu->QuestionId;\r
- Selection->Sequence = CurrentMenu->Sequence;\r
- }\r
-\r
- //\r
- // Init option as the current user's selection\r
- //\r
- InitializedFlag = TRUE;\r
- NewPos = gMenuOption.ForwardLink;\r
-\r
- gST->ConOut->EnableCursor (gST->ConOut, FALSE);\r
- UpdateStatusBar (Selection, REFRESH_STATUS_BAR, (UINT8) 0, TRUE);\r
-\r
- ControlFlag = CfInitialization;\r
- Selection->Action = UI_ACTION_NONE;\r
- while (TRUE) {\r
- switch (ControlFlag) {\r
- case CfInitialization:\r
- if (IsListEmpty (&gMenuOption)) {\r
- ControlFlag = CfReadKey;\r
- } else {\r
- ControlFlag = CfCheckSelection;\r
- }\r
- break;\r
-\r
- case CfCheckSelection:\r
- if (Selection->Action != UI_ACTION_NONE) {\r
- ControlFlag = CfExit;\r
- } else {\r
- ControlFlag = CfRepaint;\r
- }\r
- break;\r
-\r
- case CfRepaint:\r
- ControlFlag = CfRefreshHighLight;\r
-\r
- if (Repaint) {\r
- //\r
- // Display menu\r
- //\r
- DownArrow = FALSE;\r
- UpArrow = FALSE;\r
- Row = TopRow;\r
-\r
- Temp = (UINTN) SkipValue;\r
- Temp2 = (UINTN) SkipValue;\r
-\r
- //\r
- // 1. Clear the screen.\r
- //\r
- if (Selection->Form->ModalForm) {\r
- ClearLines (\r
- LocalScreen.LeftColumn + ModalSkipColumn,\r
- LocalScreen.LeftColumn + ModalSkipColumn + gPromptBlockWidth + gOptionBlockWidth,\r
- TopRow - SCROLL_ARROW_HEIGHT,\r
- BottomRow + SCROLL_ARROW_HEIGHT,\r
- PcdGet8 (PcdBrowserFieldTextColor) | FIELD_BACKGROUND\r
- ); \r
- } else {\r
- ClearLines (\r
- LocalScreen.LeftColumn,\r
- LocalScreen.RightColumn,\r
- TopRow - SCROLL_ARROW_HEIGHT,\r
- BottomRow + SCROLL_ARROW_HEIGHT,\r
- PcdGet8 (PcdBrowserFieldTextColor) | FIELD_BACKGROUND\r
- );\r
- }\r
- UiFreeRefreshList ();\r
- MinRefreshInterval = 0;\r
-\r
- //\r
- // 2.Paint the menu.\r
- //\r
- for (Link = TopOfScreen; Link != &gMenuOption; Link = Link->ForwardLink) {\r
- MenuOption = MENU_OPTION_FROM_LINK (Link);\r
- MenuOption->Row = Row;\r
- MenuOption->Col = Col;\r
- if (Selection->Form->ModalForm) {\r
- MenuOption->OptCol = gPromptBlockWidth + 1 + LocalScreen.LeftColumn + ModalSkipColumn;\r
- } else {\r
- MenuOption->OptCol = gPromptBlockWidth + 1 + LocalScreen.LeftColumn;\r
- }\r
-\r
- Statement = MenuOption->ThisTag;\r
- if (Statement->InSubtitle) {\r
- MenuOption->Col += SUBTITLE_INDENT;\r
- }\r
-\r
- if (MenuOption->GrayOut) {\r
- gST->ConOut->SetAttribute (gST->ConOut, FIELD_TEXT_GRAYED | FIELD_BACKGROUND);\r
- } else {\r
- if (Statement->Operand == EFI_IFR_SUBTITLE_OP) {\r
- gST->ConOut->SetAttribute (gST->ConOut, PcdGet8 (PcdBrowserSubtitleTextColor) | FIELD_BACKGROUND);\r
- }\r
- }\r
-\r
- Width = GetWidth (Statement, MenuOption->Handle);\r
- OriginalRow = Row;\r
- GlyphWidth = 1;\r
-\r
- if (Statement->Operand == EFI_IFR_REF_OP && MenuOption->Col >= 2) {\r
- //\r
- // Print Arrow for Goto button.\r
- //\r
- PrintAt (\r
- MenuOption->Col - 2,\r
- Row,\r
- L"%c",\r
- GEOMETRICSHAPE_RIGHT_TRIANGLE\r
- );\r
- }\r
-\r
- //\r
- // 2.1. Paint the description.\r
- //\r
- for (Index = 0; GetLineByWidth (MenuOption->Description, Width, &GlyphWidth, &Index, &OutputString) != 0x0000;) {\r
- //\r
- // Temp means need to skip how many lines from the start.\r
- //\r
- if ((Temp == 0) && (Row <= BottomRow)) {\r
- PrintStringAt (MenuOption->Col, Row, OutputString);\r
- }\r
- //\r
- // If there is more string to process print on the next row and increment the Skip value\r
- //\r
- if (StrLen (&MenuOption->Description[Index]) != 0) {\r
- if (Temp == 0) {\r
- Row++;\r
- }\r
- }\r
-\r
- FreePool (OutputString);\r
- if (Temp != 0) {\r
- Temp--;\r
- }\r
- }\r
-\r
- Temp = 0;\r
- Row = OriginalRow;\r
-\r
- //\r
- // 2.2. Paint the option string.\r
- //\r
- Status = ProcessOptions (Selection, MenuOption, FALSE, &OptionString);\r
- if (EFI_ERROR (Status)) {\r
- //\r
- // Repaint to clear possible error prompt pop-up\r
- //\r
- Repaint = TRUE;\r
- NewLine = TRUE;\r
- ControlFlag = CfRepaint;\r
- break;\r
- }\r
-\r
- if (OptionString != NULL) {\r
- if (Statement->Operand == EFI_IFR_DATE_OP || Statement->Operand == EFI_IFR_TIME_OP) {\r
- ProcessStringForDateTime(MenuOption, OptionString, TRUE);\r
- }\r
-\r
- Width = (UINT16) gOptionBlockWidth;\r
- OriginalRow = Row;\r
- GlyphWidth = 1;\r
-\r
- for (Index = 0; GetLineByWidth (OptionString, Width, &GlyphWidth, &Index, &OutputString) != 0x0000;) {\r
- if ((Temp2 == 0) && (Row <= BottomRow)) {\r
- PrintStringAt (MenuOption->OptCol, Row, OutputString);\r
- }\r
- //\r
- // If there is more string to process print on the next row and increment the Skip value\r
- //\r
- if (StrLen (&OptionString[Index]) != 0) {\r
- if (Temp2 == 0) {\r
- Row++;\r
- //\r
- // Since the Number of lines for this menu entry may or may not be reflected accurately\r
- // since the prompt might be 1 lines and option might be many, and vice versa, we need to do\r
- // some testing to ensure we are keeping this in-sync.\r
- //\r
- // If the difference in rows is greater than or equal to the skip value, increase the skip value\r
- //\r
- if ((Row - OriginalRow) >= MenuOption->Skip) {\r
- MenuOption->Skip++;\r
- }\r
- }\r
- }\r
-\r
- FreePool (OutputString);\r
- if (Temp2 != 0) {\r
- Temp2--;\r
- }\r
- }\r
-\r
- Temp2 = 0;\r
- Row = OriginalRow;\r
-\r
- FreePool (OptionString);\r
- }\r
-\r
- //\r
- // 2.4 Special process for Test opcode with test two.\r
- //\r
- if (!CompareGuid (&Statement->RefreshGuid, &gZeroGuid)) {\r
- if (gMenuEventGuidRefreshHead == NULL) {\r
- MenuUpdateEntry = AllocateZeroPool (sizeof (MENU_REFRESH_ENTRY));\r
- gMenuEventGuidRefreshHead = MenuUpdateEntry;\r
- } else {\r
- MenuUpdateEntry = gMenuEventGuidRefreshHead;\r
- while (MenuUpdateEntry->Next != NULL) {\r
- MenuUpdateEntry = MenuUpdateEntry->Next; \r
- }\r
- MenuUpdateEntry->Next = AllocateZeroPool (sizeof (MENU_REFRESH_ENTRY));\r
- MenuUpdateEntry = MenuUpdateEntry->Next; \r
- }\r
- ASSERT (MenuUpdateEntry != NULL);\r
- Status = gBS->CreateEventEx (EVT_NOTIFY_SIGNAL, TPL_NOTIFY, RefreshQuestionNotify, MenuUpdateEntry, &Statement->RefreshGuid, &MenuUpdateEntry->Event);\r
- ASSERT (!EFI_ERROR (Status));\r
- MenuUpdateEntry->MenuOption = MenuOption;\r
- MenuUpdateEntry->Selection = Selection;\r
- MenuUpdateEntry->CurrentColumn = MenuOption->OptCol;\r
- MenuUpdateEntry->CurrentRow = MenuOption->Row;\r
- if (MenuOption->GrayOut) {\r
- MenuUpdateEntry->CurrentAttribute = FIELD_TEXT_GRAYED | FIELD_BACKGROUND;\r
- } else {\r
- MenuUpdateEntry->CurrentAttribute = PcdGet8 (PcdBrowserFieldTextColor) | FIELD_BACKGROUND;\r
- }\r
- }\r
- \r
- //\r
- // If Question request refresh, register the op-code\r
- //\r
- if (Statement->RefreshInterval != 0) {\r
- //\r
- // Menu will be refreshed at minimal interval of all Questions\r
- // which have refresh request\r
- //\r
- if (MinRefreshInterval == 0 || Statement->RefreshInterval < MinRefreshInterval) {\r
- MinRefreshInterval = Statement->RefreshInterval;\r
- }\r
- \r
- if (gMenuRefreshHead == NULL) {\r
- MenuRefreshEntry = AllocateZeroPool (sizeof (MENU_REFRESH_ENTRY));\r
- gMenuRefreshHead = MenuRefreshEntry;\r
- } else {\r
- MenuRefreshEntry = gMenuRefreshHead;\r
- while (MenuRefreshEntry->Next != NULL) {\r
- MenuRefreshEntry = MenuRefreshEntry->Next; \r
- }\r
- MenuRefreshEntry->Next = AllocateZeroPool (sizeof (MENU_REFRESH_ENTRY));\r
- MenuRefreshEntry = MenuRefreshEntry->Next;\r
- }\r
- ASSERT (MenuRefreshEntry != NULL); \r
- MenuRefreshEntry->MenuOption = MenuOption;\r
- MenuRefreshEntry->Selection = Selection;\r
- MenuRefreshEntry->CurrentColumn = MenuOption->OptCol;\r
- MenuRefreshEntry->CurrentRow = MenuOption->Row;\r
- if (MenuOption->GrayOut) {\r
- MenuRefreshEntry->CurrentAttribute = FIELD_TEXT_GRAYED | FIELD_BACKGROUND;\r
- } else { \r
- MenuRefreshEntry->CurrentAttribute = PcdGet8 (PcdBrowserFieldTextColor) | FIELD_BACKGROUND;\r
- }\r
- }\r
- \r
- //\r
- // If this is a text op with secondary text information\r
- //\r
- if ((Statement->Operand == EFI_IFR_TEXT_OP) && (Statement->TextTwo != 0)) {\r
- StringPtr = GetToken (Statement->TextTwo, MenuOption->Handle);\r
-\r
- Width = (UINT16) gOptionBlockWidth;\r
- OriginalRow = Row;\r
- GlyphWidth = 1;\r
-\r
- for (Index = 0; GetLineByWidth (StringPtr, Width, &GlyphWidth, &Index, &OutputString) != 0x0000;) {\r
- if ((Temp == 0) && (Row <= BottomRow)) {\r
- PrintStringAt (MenuOption->OptCol, Row, OutputString);\r
- }\r
- //\r
- // If there is more string to process print on the next row and increment the Skip value\r
- //\r
- if (StrLen (&StringPtr[Index]) != 0) {\r
- if (Temp2 == 0) {\r
- Row++;\r
- //\r
- // Since the Number of lines for this menu entry may or may not be reflected accurately\r
- // since the prompt might be 1 lines and option might be many, and vice versa, we need to do\r
- // some testing to ensure we are keeping this in-sync.\r
- //\r
- // If the difference in rows is greater than or equal to the skip value, increase the skip value\r
- //\r
- if ((Row - OriginalRow) >= MenuOption->Skip) {\r
- MenuOption->Skip++;\r
- }\r
- }\r
- }\r
-\r
- FreePool (OutputString);\r
- if (Temp2 != 0) {\r
- Temp2--;\r
- }\r
- }\r
-\r
- Row = OriginalRow;\r
- FreePool (StringPtr);\r
- }\r
- gST->ConOut->SetAttribute (gST->ConOut, PcdGet8 (PcdBrowserFieldTextColor) | FIELD_BACKGROUND);\r
-\r
- //\r
- // 3. Update the row info which will be used by next menu.\r
- //\r
- if (Link == TopOfScreen) {\r
- Row += MenuOption->Skip - SkipValue;\r
- } else {\r
- Row += MenuOption->Skip;\r
- }\r
-\r
- if (Row > BottomRow) {\r
- if (!ValueIsScroll (FALSE, Link)) {\r
- DownArrow = TRUE;\r
- }\r
-\r
- Row = BottomRow + 1;\r
- break;\r
- }\r
- }\r
-\r
- if (!ValueIsScroll (TRUE, TopOfScreen)) {\r
- UpArrow = TRUE;\r
- }\r
-\r
- if (UpArrow) {\r
- gST->ConOut->SetAttribute (gST->ConOut, ARROW_TEXT | ARROW_BACKGROUND);\r
- PrintAt (\r
- LocalScreen.LeftColumn + gPromptBlockWidth + gOptionBlockWidth + 1,\r
- TopRow - SCROLL_ARROW_HEIGHT,\r
- L"%c",\r
- ARROW_UP\r
- );\r
- gST->ConOut->SetAttribute (gST->ConOut, PcdGet8 (PcdBrowserFieldTextColor) | FIELD_BACKGROUND);\r
- }\r
-\r
- if (DownArrow) {\r
- gST->ConOut->SetAttribute (gST->ConOut, ARROW_TEXT | ARROW_BACKGROUND);\r
- PrintAt (\r
- LocalScreen.LeftColumn + gPromptBlockWidth + gOptionBlockWidth + 1,\r
- BottomRow + SCROLL_ARROW_HEIGHT,\r
- L"%c",\r
- ARROW_DOWN\r
- );\r
- gST->ConOut->SetAttribute (gST->ConOut, PcdGet8 (PcdBrowserFieldTextColor) | FIELD_BACKGROUND);\r
- }\r
-\r
- MenuOption = NULL;\r
- }\r
- break;\r
-\r
- case CfRefreshHighLight:\r
- //\r
- // MenuOption: Last menu option that need to remove hilight\r
- // MenuOption is set to NULL in Repaint\r
- // NewPos: Current menu option that need to hilight\r
- //\r
- ControlFlag = CfUpdateHelpString;\r
- if (TopOfScreen == &MenuOption->Link) {\r
- Temp = SkipValue;\r
- } else {\r
- Temp = 0;\r
- }\r
- if (NewPos == TopOfScreen) {\r
- Temp2 = SkipValue;\r
- } else {\r
- Temp2 = 0;\r
- }\r
- if (InitializedFlag) {\r
- InitializedFlag = FALSE;\r
- MoveToNextStatement (Selection, FALSE, &NewPos, BottomRow - TopRow);\r
- }\r
-\r
- //\r
- // Repaint flag is normally reset when finish processing CfUpdateHelpString. Temporarily\r
- // reset Repaint flag because we may break halfway and skip CfUpdateHelpString processing.\r
- //\r
- SavedValue = Repaint;\r
- Repaint = FALSE;\r
-\r
- if (Selection->QuestionId != 0) {\r
- NewPos = gMenuOption.ForwardLink;\r
- SavedMenuOption = MENU_OPTION_FROM_LINK (NewPos);\r
-\r
- while ((SavedMenuOption->ThisTag->QuestionId != Selection->QuestionId ||\r
- SavedMenuOption->Sequence != Selection->Sequence) &&\r
- NewPos->ForwardLink != &gMenuOption) {\r
- NewPos = NewPos->ForwardLink;\r
- SavedMenuOption = MENU_OPTION_FROM_LINK (NewPos);\r
- }\r
- if (SavedMenuOption->ThisTag->QuestionId == Selection->QuestionId) {\r
- //\r
- // Target Question found, find its MenuOption\r
- //\r
- Link = TopOfScreen;\r
-\r
- for (Index = TopRow; Index <= BottomRow && Link != NewPos;) {\r
- SavedMenuOption = MENU_OPTION_FROM_LINK (Link);\r
- Index += SavedMenuOption->Skip;\r
- if (Link == TopOfScreen) {\r
- Index -= SkipValue;\r
- }\r
- Link = Link->ForwardLink;\r
- }\r
- if (NewPos == Link) {\r
- SavedMenuOption = MENU_OPTION_FROM_LINK (Link);\r
- }\r
-\r
- //\r
- // Not find the selected menu in current show page.\r
- // Have two case to enter this if:\r
- // 1. Not find the menu at current page.\r
- // 2. Find the menu in current page, but the menu shows at the bottom and not all info shows.\r
- // For case 2, has an exception: The menu can show more than one pages and now only this menu shows.\r
- //\r
- // Base on the selected menu will show at the bottom of the page,\r
- // select the menu which will show at the top of the page.\r
- //\r
- if (Link != NewPos || Index > BottomRow || \r
- (Link == NewPos && (SavedMenuOption->Row + SavedMenuOption->Skip - 1 > BottomRow) && (Link != TopOfScreen))) {\r
- //\r
- // Find the MenuOption which has the skip value for Date/Time opcode. \r
- //\r
- AdjustDateAndTimePosition(FALSE, &NewPos);\r
- //\r
- // NewPos is not in the current page, simply scroll page so that NewPos is in the end of the page\r
- //\r
- SavedMenuOption = MENU_OPTION_FROM_LINK (NewPos);\r
- //\r
- // SavedMenuOption->Row == 0 means the menu not show yet.\r
- //\r
- if (SavedMenuOption->Row == 0) {\r
- UpdateOptionSkipLines (Selection, SavedMenuOption);\r
- }\r
-\r
- //\r
- // Base on the selected menu will show at the bottome of next page, \r
- // select the menu show at the top of the next page. \r
- //\r
- Link = NewPos;\r
- for (Index = TopRow + SavedMenuOption->Skip; Index <= BottomRow + 1; ) { \r
- Link = Link->BackLink;\r
- SavedMenuOption = MENU_OPTION_FROM_LINK (Link);\r
- if (SavedMenuOption->Row == 0) {\r
- UpdateOptionSkipLines (Selection, SavedMenuOption);\r
- }\r
- Index += SavedMenuOption->Skip;\r
- }\r
-\r
- //\r
- // Found the menu which will show at the top of the page.\r
- //\r
- if (Link == NewPos) {\r
- //\r
- // The menu can show more than one pages, just show the menu at the top of the page.\r
- //\r
- SkipValue = 0;\r
- TopOfScreen = Link;\r
- } else {\r
- //\r
- // Check whether need to skip some line for menu shows at the top of the page.\r
- //\r
- SkipValue = Index - BottomRow - 1;\r
- if (SkipValue > 0 && SkipValue < (INTN) SavedMenuOption->Skip) {\r
- TopOfScreen = Link;\r
- } else {\r
- SkipValue = 0;\r
- TopOfScreen = Link->ForwardLink;\r
- }\r
- }\r
-\r
- Repaint = TRUE;\r
- NewLine = TRUE;\r
- ControlFlag = CfRepaint;\r
- break;\r
- }\r
- } else {\r
- //\r
- // Target Question not found, highlight the default menu option\r
- //\r
- NewPos = TopOfScreen;\r
- }\r
-\r
- Selection->QuestionId = 0;\r
- }\r
-\r
- if (NewPos != NULL && (MenuOption == NULL || NewPos != &MenuOption->Link)) {\r
- if (MenuOption != NULL) {\r
- //\r
- // Remove highlight on last Menu Option\r
- //\r
- gST->ConOut->SetCursorPosition (gST->ConOut, MenuOption->Col, MenuOption->Row);\r
- ProcessOptions (Selection, MenuOption, FALSE, &OptionString);\r
- gST->ConOut->SetAttribute (gST->ConOut, PcdGet8 (PcdBrowserFieldTextColor) | FIELD_BACKGROUND);\r
- if (OptionString != NULL) {\r
- if ((MenuOption->ThisTag->Operand == EFI_IFR_DATE_OP) ||\r
- (MenuOption->ThisTag->Operand == EFI_IFR_TIME_OP)\r
- ) {\r
- ProcessStringForDateTime(MenuOption, OptionString, FALSE);\r
- }\r
-\r
- Width = (UINT16) gOptionBlockWidth;\r
- OriginalRow = MenuOption->Row;\r
- GlyphWidth = 1;\r
-\r
- for (Index = 0; GetLineByWidth (OptionString, Width, &GlyphWidth, &Index, &OutputString) != 0x0000;) {\r
- if ((Temp == 0) && (MenuOption->Row >= TopRow) && (MenuOption->Row <= BottomRow)) {\r
- PrintStringAt (MenuOption->OptCol, MenuOption->Row, OutputString);\r
- }\r
- //\r
- // If there is more string to process print on the next row and increment the Skip value\r
- //\r
- if (StrLen (&OptionString[Index]) != 0) {\r
- if (Temp == 0) {\r
- MenuOption->Row++;\r
- }\r
- }\r
-\r
- FreePool (OutputString);\r
- if (Temp != 0) {\r
- Temp--;\r
- }\r
- }\r
-\r
- MenuOption->Row = OriginalRow;\r
-\r
- FreePool (OptionString);\r
- } else {\r
- if (NewLine) {\r
- if (MenuOption->GrayOut) {\r
- gST->ConOut->SetAttribute (gST->ConOut, FIELD_TEXT_GRAYED | FIELD_BACKGROUND);\r
- } else if (MenuOption->ThisTag->Operand == EFI_IFR_SUBTITLE_OP) {\r
- gST->ConOut->SetAttribute (gST->ConOut, PcdGet8 (PcdBrowserSubtitleTextColor) | FIELD_BACKGROUND);\r
- }\r
-\r
- OriginalRow = MenuOption->Row;\r
- Width = GetWidth (MenuOption->ThisTag, MenuOption->Handle);\r
- GlyphWidth = 1;\r
-\r
- for (Index = 0; GetLineByWidth (MenuOption->Description, Width, &GlyphWidth, &Index, &OutputString) != 0x0000;) {\r
- if ((Temp == 0) && (MenuOption->Row >= TopRow) && (MenuOption->Row <= BottomRow)) {\r
- PrintStringAt (MenuOption->Col, MenuOption->Row, OutputString);\r
- }\r
- //\r
- // If there is more string to process print on the next row and increment the Skip value\r
- //\r
- if (StrLen (&MenuOption->Description[Index]) != 0) {\r
- if (Temp == 0) {\r
- MenuOption->Row++;\r
- }\r
- }\r
-\r
- FreePool (OutputString);\r
- if (Temp != 0) {\r
- Temp--;\r
- }\r
- }\r
-\r
- MenuOption->Row = OriginalRow;\r
- gST->ConOut->SetAttribute (gST->ConOut, PcdGet8 (PcdBrowserFieldTextColor) | FIELD_BACKGROUND);\r
- }\r
- }\r
- }\r
-\r
- //\r
- // This is the current selected statement\r
- //\r
- MenuOption = MENU_OPTION_FROM_LINK (NewPos);\r
- Statement = MenuOption->ThisTag;\r
- Selection->Statement = Statement;\r
- if (!IsSelectable (MenuOption)) {\r
- Repaint = SavedValue;\r
- UpdateKeyHelp (Selection, MenuOption, FALSE);\r
- break;\r
- }\r
-\r
- //\r
- // Record highlight for current menu\r
- //\r
- CurrentMenu->QuestionId = Statement->QuestionId;\r
- CurrentMenu->Sequence = MenuOption->Sequence;\r
-\r
- //\r
- // Set reverse attribute\r
- //\r
- gST->ConOut->SetAttribute (gST->ConOut, PcdGet8 (PcdBrowserFieldTextHighlightColor) | PcdGet8 (PcdBrowserFieldBackgroundHighlightColor));\r
- gST->ConOut->SetCursorPosition (gST->ConOut, MenuOption->Col, MenuOption->Row);\r
-\r
- //\r
- // Assuming that we have a refresh linked-list created, lets annotate the\r
- // appropriate entry that we are highlighting with its new attribute. Just prior to this\r
- // lets reset all of the entries' attribute so we do not get multiple highlights in he refresh\r
- //\r
- if (gMenuRefreshHead != NULL) {\r
- for (MenuRefreshEntry = gMenuRefreshHead; MenuRefreshEntry != NULL; MenuRefreshEntry = MenuRefreshEntry->Next) {\r
- if (MenuRefreshEntry->MenuOption->GrayOut) {\r
- MenuRefreshEntry->CurrentAttribute = FIELD_TEXT_GRAYED | FIELD_BACKGROUND;\r
- } else { \r
- MenuRefreshEntry->CurrentAttribute = PcdGet8 (PcdBrowserFieldTextColor) | FIELD_BACKGROUND;\r
- }\r
- if (MenuRefreshEntry->MenuOption == MenuOption) {\r
- MenuRefreshEntry->CurrentAttribute = PcdGet8 (PcdBrowserFieldTextHighlightColor) | PcdGet8 (PcdBrowserFieldBackgroundHighlightColor);\r
- }\r
- }\r
- }\r
-\r
- ProcessOptions (Selection, MenuOption, FALSE, &OptionString);\r
- if (OptionString != NULL) {\r
- if (Statement->Operand == EFI_IFR_DATE_OP || Statement->Operand == EFI_IFR_TIME_OP) {\r
- ProcessStringForDateTime(MenuOption, OptionString, FALSE);\r
- }\r
- Width = (UINT16) gOptionBlockWidth;\r
-\r
- OriginalRow = MenuOption->Row;\r
- GlyphWidth = 1;\r
-\r
- for (Index = 0; GetLineByWidth (OptionString, Width, &GlyphWidth, &Index, &OutputString) != 0x0000;) {\r
- if ((Temp2 == 0) && (MenuOption->Row >= TopRow) && (MenuOption->Row <= BottomRow) ) {\r
- PrintStringAt (MenuOption->OptCol, MenuOption->Row, OutputString);\r
- }\r
- //\r
- // If there is more string to process print on the next row and increment the Skip value\r
- //\r
- if (StrLen (&OptionString[Index]) != 0) {\r
- if (Temp2 == 0) {\r
- MenuOption->Row++;\r
- }\r
- }\r
-\r
- FreePool (OutputString);\r
- if (Temp2 != 0) {\r
- Temp2--;\r
- }\r
- }\r
-\r
- MenuOption->Row = OriginalRow;\r
-\r
- FreePool (OptionString);\r
- } else {\r
- if (NewLine) {\r
- OriginalRow = MenuOption->Row;\r
-\r
- Width = GetWidth (Statement, MenuOption->Handle);\r
- GlyphWidth = 1;\r
-\r
- for (Index = 0; GetLineByWidth (MenuOption->Description, Width, &GlyphWidth, &Index, &OutputString) != 0x0000;) {\r
- if ((Temp2 == 0) && (MenuOption->Row >= TopRow) && (MenuOption->Row <= BottomRow) ) {\r
- PrintStringAt (MenuOption->Col, MenuOption->Row, OutputString);\r
- }\r
- //\r
- // If there is more string to process print on the next row and increment the Skip value\r
- //\r
- if (StrLen (&MenuOption->Description[Index]) != 0) {\r
- if (Temp2 == 0) {\r
- MenuOption->Row++;\r
- }\r
- }\r
-\r
- FreePool (OutputString);\r
- if (Temp2 != 0) {\r
- Temp2--;\r
- }\r
- }\r
-\r
- MenuOption->Row = OriginalRow;\r
-\r
- }\r
- }\r
-\r
- UpdateKeyHelp (Selection, MenuOption, FALSE);\r
-\r
- //\r
- // Clear reverse attribute\r
- //\r
- gST->ConOut->SetAttribute (gST->ConOut, PcdGet8 (PcdBrowserFieldTextColor) | FIELD_BACKGROUND);\r
- }\r
- //\r
- // Repaint flag will be used when process CfUpdateHelpString, so restore its value\r
- // if we didn't break halfway when process CfRefreshHighLight.\r
- //\r
- Repaint = SavedValue;\r
- break;\r
-\r
- case CfUpdateHelpString:\r
- ControlFlag = CfPrepareToReadKey;\r
- if (Selection->Form->ModalForm) {\r
- break;\r
- }\r
-\r
- if (Repaint || NewLine) {\r
- //\r
- // Don't print anything if it is a NULL help token\r
- //\r
- ASSERT(MenuOption != NULL);\r
- if (MenuOption->ThisTag->Help == 0 || !IsSelectable (MenuOption)) {\r
- StringPtr = L"\0";\r
- } else {\r
- StringPtr = GetToken (MenuOption->ThisTag->Help, MenuOption->Handle);\r
- }\r
-\r
- RowCount = BottomRow - TopRow;\r
- HelpPageIndex = 0;\r
- //\r
- // 1.Calculate how many line the help string need to print.\r
- //\r
- if (HelpString != NULL) {\r
- FreePool (HelpString);\r
- }\r
- HelpLine = ProcessHelpString (StringPtr, &HelpString, &EachLineWidth, RowCount);\r
- if (HelpLine > RowCount) {\r
- MultiHelpPage = TRUE;\r
- StringPtr = GetToken (STRING_TOKEN(ADJUST_HELP_PAGE_UP), gHiiHandle);\r
- if (HelpHeaderString != NULL) {\r
- FreePool (HelpHeaderString);\r
- }\r
- HelpHeaderLine = ProcessHelpString (StringPtr, &HelpHeaderString, &HeaderLineWidth, RowCount);\r
- StringPtr = GetToken (STRING_TOKEN(ADJUST_HELP_PAGE_DOWN), gHiiHandle);\r
- if (HelpBottomString != NULL) {\r
- FreePool (HelpBottomString);\r
- }\r
- HelpBottomLine = ProcessHelpString (StringPtr, &HelpBottomString, &BottomLineWidth, RowCount);\r
- //\r
- // Calculate the help page count.\r
- //\r
- if (HelpLine > 2 * RowCount - 2) {\r
- HelpPageCount = (HelpLine - RowCount + 1) / (RowCount - 2) + 1;\r
- if ((HelpLine - RowCount + 1) % (RowCount - 2) > 1) {\r
- HelpPageCount += 1;\r
- }\r
- } else {\r
- HelpPageCount = 2;\r
- }\r
- } else {\r
- MultiHelpPage = FALSE;\r
- }\r
- }\r
-\r
- //\r
- // Clean the help field first.\r
- //\r
- ClearLines (\r
- LocalScreen.RightColumn - gHelpBlockWidth,\r
- LocalScreen.RightColumn,\r
- TopRow,\r
- BottomRow,\r
- PcdGet8 (PcdBrowserFieldTextColor) | FIELD_BACKGROUND\r
- );\r
-\r
- //\r
- // Check whether need to show the 'More(U/u)' at the begin.\r
- // Base on current direct info, here shows aligned to the right side of the column.\r
- // If the direction is multi line and aligned to right side may have problem, so \r
- // add ASSERT code here.\r
- //\r
- if (HelpPageIndex > 0) {\r
- gST->ConOut->SetAttribute (gST->ConOut, INFO_TEXT | FIELD_BACKGROUND);\r
- for (Index = 0; Index < HelpHeaderLine; Index++) {\r
- ASSERT (HelpHeaderLine == 1);\r
- ASSERT (GetStringWidth (HelpHeaderString) / 2 < (UINTN) (gHelpBlockWidth - 1));\r
- PrintStringAt (\r
- LocalScreen.RightColumn - GetStringWidth (HelpHeaderString) / 2 - 1,\r
- Index + TopRow,\r
- &HelpHeaderString[Index * HeaderLineWidth]\r
- );\r
- }\r
- }\r
-\r
- gST->ConOut->SetAttribute (gST->ConOut, HELP_TEXT | FIELD_BACKGROUND);\r
- //\r
- // Print the help string info.\r
- //\r
- if (!MultiHelpPage) {\r
- for (Index = 0; Index < HelpLine; Index++) {\r
- PrintStringAt (\r
- LocalScreen.RightColumn - gHelpBlockWidth,\r
- Index + TopRow,\r
- &HelpString[Index * EachLineWidth]\r
- );\r
- }\r
- gST->ConOut->SetCursorPosition(gST->ConOut, LocalScreen.RightColumn-1, BottomRow);\r
- } else {\r
- if (HelpPageIndex == 0) {\r
- for (Index = 0; Index < RowCount - HelpBottomLine; Index++) {\r
- PrintStringAt (\r
- LocalScreen.RightColumn - gHelpBlockWidth,\r
- Index + TopRow,\r
- &HelpString[Index * EachLineWidth]\r
- );\r
- }\r
- } else {\r
- for (Index = 0; (Index < RowCount - HelpBottomLine - HelpHeaderLine) && \r
- (Index + HelpPageIndex * (RowCount - 2) + 1 < HelpLine); Index++) {\r
- PrintStringAt (\r
- LocalScreen.RightColumn - gHelpBlockWidth,\r
- Index + TopRow + HelpHeaderLine,\r
- &HelpString[(Index + HelpPageIndex * (RowCount - 2) + 1)* EachLineWidth]\r
- );\r
- }\r
- if (HelpPageIndex == HelpPageCount - 1) {\r
- gST->ConOut->SetCursorPosition(gST->ConOut, LocalScreen.RightColumn-1, BottomRow);\r
- }\r
- } \r
- }\r
-\r
- //\r
- // Check whether need to print the 'More(D/d)' at the bottom.\r
- // Base on current direct info, here shows aligned to the right side of the column.\r
- // If the direction is multi line and aligned to right side may have problem, so \r
- // add ASSERT code here.\r
- //\r
- if (HelpPageIndex < HelpPageCount - 1 && MultiHelpPage) {\r
- gST->ConOut->SetAttribute (gST->ConOut, INFO_TEXT | FIELD_BACKGROUND);\r
- for (Index = 0; Index < HelpBottomLine; Index++) {\r
- ASSERT (HelpBottomLine == 1);\r
- ASSERT (GetStringWidth (HelpBottomString) / 2 < (UINTN) (gHelpBlockWidth - 1)); \r
- PrintStringAt (\r
- LocalScreen.RightColumn - GetStringWidth (HelpBottomString) / 2 - 1,\r
- Index + BottomRow - HelpBottomLine,\r
- &HelpBottomString[Index * BottomLineWidth]\r
- );\r
- }\r
- }\r
- //\r
- // Reset this flag every time we finish using it.\r
- //\r
- Repaint = FALSE;\r
- NewLine = FALSE;\r
- break;\r
-\r
- case CfPrepareToReadKey:\r
- ControlFlag = CfReadKey;\r
- ScreenOperation = UiNoOperation;\r
- break;\r
-\r
- case CfReadKey:\r
- ControlFlag = CfScreenOperation;\r
-\r
- //\r
- // Wait for user's selection\r
- //\r
- while (TRUE) {\r
- Status = gST->ConIn->ReadKeyStroke (gST->ConIn, &Key);\r
- if (!EFI_ERROR (Status)) {\r
- break;\r
- }\r
-\r
- //\r
- // If we encounter error, continue to read another key in.\r
- //\r
- if (Status != EFI_NOT_READY) {\r
- continue;\r
- }\r
-\r
- Status = UiWaitForSingleEvent (gST->ConIn->WaitForKey, 0, MinRefreshInterval);\r
- ASSERT_EFI_ERROR (Status);\r
-\r
- if (Selection->Action == UI_ACTION_REFRESH_FORMSET) {\r
- //\r
- // IFR is updated in Callback of refresh opcode, re-parse it\r
- //\r
- ControlFlag = CfCheckSelection;\r
- Selection->Statement = NULL;\r
- break;\r
- }\r
- }\r
-\r
- if (ControlFlag == CfCheckSelection) {\r
- break;\r
- }\r
-\r
- switch (Key.UnicodeChar) {\r
- case CHAR_CARRIAGE_RETURN:\r
- if(MenuOption->GrayOut || MenuOption->ReadOnly) {\r
- ControlFlag = CfReadKey;\r
- break;\r
- }\r
-\r
- ScreenOperation = UiSelect;\r
- gDirection = 0;\r
- break;\r
-\r
- //\r
- // We will push the adjustment of these numeric values directly to the input handler\r
- // NOTE: we won't handle manual input numeric\r
- //\r
- case '+':\r
- case '-':\r
- //\r
- // If the screen has no menu items, and the user didn't select UiReset\r
- // ignore the selection and go back to reading keys.\r
- //\r
- if(IsListEmpty (&gMenuOption) || MenuOption->GrayOut || MenuOption->ReadOnly) {\r
- ControlFlag = CfReadKey;\r
- break;\r
- }\r
-\r
- ASSERT(MenuOption != NULL);\r
- Statement = MenuOption->ThisTag;\r
- if ((Statement->Operand == EFI_IFR_DATE_OP)\r
- || (Statement->Operand == EFI_IFR_TIME_OP)\r
- || ((Statement->Operand == EFI_IFR_NUMERIC_OP) && (Statement->Step != 0))\r
- ){\r
- if (Key.UnicodeChar == '+') {\r
- gDirection = SCAN_RIGHT;\r
- } else {\r
- gDirection = SCAN_LEFT;\r
- }\r
- Status = ProcessOptions (Selection, MenuOption, TRUE, &OptionString);\r
- if (EFI_ERROR (Status)) {\r
- //\r
- // Repaint to clear possible error prompt pop-up\r
- //\r
- Repaint = TRUE;\r
- NewLine = TRUE;\r
- } else {\r
- Selection->Action = UI_ACTION_REFRESH_FORM;\r
- }\r
- if (OptionString != NULL) {\r
- FreePool (OptionString);\r
- }\r
- }\r
- break;\r
-\r
- case '^':\r
- ScreenOperation = UiUp;\r
- break;\r
-\r
- case 'V':\r
- case 'v':\r
- ScreenOperation = UiDown;\r
- break;\r
-\r
- case ' ':\r
- if ((gClassOfVfr & FORMSET_CLASS_FRONT_PAGE) != FORMSET_CLASS_FRONT_PAGE) {\r
- //\r
- // If the screen has no menu items, and the user didn't select UiReset\r
- // ignore the selection and go back to reading keys.\r
- //\r
- if(IsListEmpty (&gMenuOption)) {\r
- ControlFlag = CfReadKey;\r
- break;\r
- }\r
- \r
- ASSERT(MenuOption != NULL);\r
- if (MenuOption->ThisTag->Operand == EFI_IFR_CHECKBOX_OP && !MenuOption->GrayOut && !MenuOption->ReadOnly) {\r
- ScreenOperation = UiSelect;\r
- }\r
- }\r
- break;\r
-\r
- case 'D':\r
- case 'd':\r
- if (!MultiHelpPage) {\r
- ControlFlag = CfReadKey;\r
- break;\r
- }\r
- ControlFlag = CfUpdateHelpString;\r
- HelpPageIndex = HelpPageIndex < HelpPageCount - 1 ? HelpPageIndex + 1 : HelpPageCount - 1;\r
- break;\r
-\r
- case 'U':\r
- case 'u':\r
- if (!MultiHelpPage) {\r
- ControlFlag = CfReadKey;\r
- break;\r
- }\r
- ControlFlag = CfUpdateHelpString;\r
- HelpPageIndex = HelpPageIndex > 0 ? HelpPageIndex - 1 : 0;\r
- break;\r
-\r
- case CHAR_NULL:\r
- for (Index = 0; Index < mScanCodeNumber; Index++) {\r
- if (Key.ScanCode == gScanCodeToOperation[Index].ScanCode) {\r
- ScreenOperation = gScanCodeToOperation[Index].ScreenOperation;\r
- break;\r
- }\r
- }\r
- \r
- if (Selection->Form->ModalForm && (Key.ScanCode == SCAN_ESC || Index == mScanCodeNumber)) {\r
- //\r
- // ModalForm has no ESC key and Hot Key.\r
- //\r
- ControlFlag = CfReadKey;\r
- } else if (Index == mScanCodeNumber) {\r
- //\r
- // Check whether Key matches the registered hot key.\r
- //\r
- HotKey = NULL;\r
- if ((gBrowserSettingScope == SystemLevel) || \r
- (Selection->FormEditable && gFunctionKeySetting != NONE_FUNCTION_KEY_SETTING)) {\r
- HotKey = GetHotKeyFromRegisterList (&Key);\r
- }\r
- if (HotKey != NULL) {\r
- ScreenOperation = UiHotKey;\r
- }\r
- }\r
- break;\r
- }\r
- break;\r
-\r
- case CfScreenOperation:\r
- if (ScreenOperation != UiReset) {\r
- //\r
- // If the screen has no menu items, and the user didn't select UiReset\r
- // ignore the selection and go back to reading keys.\r
- //\r
- if (IsListEmpty (&gMenuOption)) {\r
- ControlFlag = CfReadKey;\r
- break;\r
- }\r
- }\r
-\r
- for (Index = 0;\r
- Index < sizeof (gScreenOperationToControlFlag) / sizeof (gScreenOperationToControlFlag[0]);\r
- Index++\r
- ) {\r
- if (ScreenOperation == gScreenOperationToControlFlag[Index].ScreenOperation) {\r
- ControlFlag = gScreenOperationToControlFlag[Index].ControlFlag;\r
- break;\r
- }\r
- }\r
- break;\r
-\r
- case CfUiSelect:\r
- ControlFlag = CfCheckSelection;\r
-\r
- ASSERT(MenuOption != NULL);\r
- Statement = MenuOption->ThisTag;\r
- if (Statement->Operand == EFI_IFR_TEXT_OP) {\r
- break;\r
- }\r
-\r
- //\r
- // Keep highlight on current MenuOption\r
- //\r
- Selection->QuestionId = Statement->QuestionId;\r
-\r
- switch (Statement->Operand) {\r
- case EFI_IFR_REF_OP:\r
- ProcessGotoOpCode(Statement, Selection, &Repaint, &NewLine);\r
- break;\r
-\r
- case EFI_IFR_ACTION_OP:\r
- //\r
- // Process the Config string <ConfigResp>\r
- //\r
- Status = ProcessQuestionConfig (Selection, Statement);\r
-\r
- if (EFI_ERROR (Status)) {\r
- break;\r
- }\r
-\r
- //\r
- // The action button may change some Question value, so refresh the form\r
- //\r
- Selection->Action = UI_ACTION_REFRESH_FORM;\r
- break;\r
-\r
- case EFI_IFR_RESET_BUTTON_OP:\r
- //\r
- // Reset Question to default value specified by DefaultId\r
- //\r
- ControlFlag = CfUiDefault;\r
- DefaultId = Statement->DefaultId;\r
- break;\r
-\r
- default:\r
- //\r
- // Editable Questions: oneof, ordered list, checkbox, numeric, string, password\r
- //\r
- UpdateKeyHelp (Selection, MenuOption, TRUE);\r
- Status = ProcessOptions (Selection, MenuOption, TRUE, &OptionString);\r
-\r
- if (EFI_ERROR (Status)) {\r
- Repaint = TRUE;\r
- NewLine = TRUE;\r
- UpdateKeyHelp (Selection, MenuOption, FALSE);\r
- } else {\r
- Selection->Action = UI_ACTION_REFRESH_FORM;\r
- }\r
-\r
- if (OptionString != NULL) {\r
- FreePool (OptionString);\r
- }\r
- break;\r
- }\r
- break;\r
-\r
- case CfUiReset:\r
- //\r
- // We come here when someone press ESC\r
- //\r
- ControlFlag = CfCheckSelection;\r
- FindNextMenu (Selection, &Repaint, &NewLine);\r
- break;\r
-\r
- case CfUiLeft:\r
- ControlFlag = CfCheckSelection;\r
- ASSERT(MenuOption != NULL);\r
- if ((MenuOption->ThisTag->Operand == EFI_IFR_DATE_OP) || (MenuOption->ThisTag->Operand == EFI_IFR_TIME_OP)) {\r
- if (MenuOption->Sequence != 0) {\r
- //\r
- // In the middle or tail of the Date/Time op-code set, go left.\r
- //\r
- ASSERT(NewPos != NULL);\r
- NewPos = NewPos->BackLink;\r
- }\r
- }\r
- break;\r
-\r
- case CfUiRight:\r
- ControlFlag = CfCheckSelection;\r
- ASSERT(MenuOption != NULL);\r
- if ((MenuOption->ThisTag->Operand == EFI_IFR_DATE_OP) || (MenuOption->ThisTag->Operand == EFI_IFR_TIME_OP)) {\r
- if (MenuOption->Sequence != 2) {\r
- //\r
- // In the middle or tail of the Date/Time op-code set, go left.\r
- //\r
- ASSERT(NewPos != NULL);\r
- NewPos = NewPos->ForwardLink;\r
- }\r
- }\r
- break;\r
-\r
- case CfUiUp:\r
- ControlFlag = CfCheckSelection;\r
-\r
- SavedListEntry = NewPos;\r
-\r
- ASSERT(NewPos != NULL);\r
- //\r
- // Adjust Date/Time position before we advance forward.\r
- //\r
- AdjustDateAndTimePosition (TRUE, &NewPos);\r
- if (NewPos->BackLink != &gMenuOption) {\r
- MenuOption = MENU_OPTION_FROM_LINK (NewPos);\r
- ASSERT (MenuOption != NULL);\r
- NewLine = TRUE;\r
- NewPos = NewPos->BackLink;\r
-\r
- PreviousMenuOption = MENU_OPTION_FROM_LINK (NewPos);\r
- if (PreviousMenuOption->Row == 0) {\r
- UpdateOptionSkipLines (Selection, PreviousMenuOption);\r
- }\r
- DistanceValue = PreviousMenuOption->Skip;\r
- Difference = 0;\r
- if (MenuOption->Row >= DistanceValue + TopRow) {\r
- Difference = MoveToNextStatement (Selection, TRUE, &NewPos, MenuOption->Row - TopRow - DistanceValue);\r
- }\r
- NextMenuOption = MENU_OPTION_FROM_LINK (NewPos);\r
- \r
- if (Difference < 0) {\r
- //\r
- // We hit the begining MenuOption that can be focused\r
- // so we simply scroll to the top.\r
- //\r
- if (TopOfScreen != gMenuOption.ForwardLink) {\r
- TopOfScreen = gMenuOption.ForwardLink;\r
- Repaint = TRUE;\r
- } else {\r
- //\r
- // Scroll up to the last page when we have arrived at top page.\r
- //\r
- NewPos = &gMenuOption;\r
- TopOfScreen = &gMenuOption;\r
- MenuOption = MENU_OPTION_FROM_LINK (SavedListEntry);\r
- ScreenOperation = UiPageUp;\r
- ControlFlag = CfScreenOperation;\r
- break;\r
- }\r
- } else if (MenuOption->Row < TopRow + DistanceValue + Difference) {\r
- //\r
- // Previous focus MenuOption is above the TopOfScreen, so we need to scroll\r
- //\r
- TopOfScreen = NewPos;\r
- Repaint = TRUE;\r
- SkipValue = 0;\r
- } else if (!IsSelectable (NextMenuOption)) {\r
- //\r
- // Continue to go up until scroll to next page or the selectable option is found.\r
- //\r
- ScreenOperation = UiUp;\r
- ControlFlag = CfScreenOperation;\r
- }\r
-\r
- //\r
- // If we encounter a Date/Time op-code set, rewind to the first op-code of the set.\r
- //\r
- AdjustDateAndTimePosition (TRUE, &TopOfScreen);\r
- AdjustDateAndTimePosition (TRUE, &NewPos);\r
- MenuOption = MENU_OPTION_FROM_LINK (SavedListEntry);\r
- UpdateStatusBar (Selection, INPUT_ERROR, MenuOption->ThisTag->QuestionFlags, FALSE);\r
- } else {\r
- //\r
- // Scroll up to the last page.\r
- //\r
- NewPos = &gMenuOption;\r
- TopOfScreen = &gMenuOption;\r
- MenuOption = MENU_OPTION_FROM_LINK (SavedListEntry);\r
- ScreenOperation = UiPageUp;\r
- ControlFlag = CfScreenOperation;\r
- }\r
- break;\r
-\r
- case CfUiPageUp:\r
- //\r
- // SkipValue means lines is skipped when show the top menu option.\r
- //\r
- ControlFlag = CfCheckSelection;\r
-\r
- ASSERT(NewPos != NULL);\r
- //\r
- // Already at the first menu option, so do nothing.\r
- //\r
- if (NewPos->BackLink == &gMenuOption) {\r
- NewLine = FALSE;\r
- Repaint = FALSE;\r
- break;\r
- }\r
-\r
- NewLine = TRUE;\r
- Repaint = TRUE;\r
-\r
- //\r
- // SkipValue > (BottomRow - TopRow + 1) means current menu has more than one\r
- // form of options to be show, so just update the SkipValue to show the next\r
- // parts of options.\r
- //\r
- if (SkipValue > (INTN) (BottomRow - TopRow + 1)) {\r
- SkipValue -= BottomRow - TopRow + 1;\r
- break;\r
- }\r
-\r
- Link = TopOfScreen;\r
- //\r
- // First minus the menu of the top screen, it's value is SkipValue.\r
- //\r
- Index = (BottomRow + 1) - SkipValue;\r
- while ((Index >= TopRow) && (Link->BackLink != &gMenuOption)) {\r
- Link = Link->BackLink;\r
- PreviousMenuOption = MENU_OPTION_FROM_LINK (Link);\r
- if (PreviousMenuOption->Row == 0) {\r
- UpdateOptionSkipLines (Selection, PreviousMenuOption);\r
- } \r
- if (Index < PreviousMenuOption->Skip) {\r
- break;\r
- }\r
- Index = Index - PreviousMenuOption->Skip;\r
- }\r
- \r
- if ((Link->BackLink == &gMenuOption) && (Index >= TopRow)) {\r
- SkipValue = 0;\r
- if (TopOfScreen == &gMenuOption) {\r
- TopOfScreen = gMenuOption.ForwardLink;\r
- NewPos = gMenuOption.BackLink;\r
- MoveToNextStatement (Selection, TRUE, &NewPos, BottomRow - TopRow);\r
- Repaint = FALSE;\r
- } else if (TopOfScreen != Link) {\r
- TopOfScreen = Link;\r
- NewPos = Link;\r
- MoveToNextStatement (Selection, FALSE, &NewPos, BottomRow - TopRow);\r
- } else {\r
- //\r
- // Finally we know that NewPos is the last MenuOption can be focused.\r
- //\r
- Repaint = FALSE;\r
- NewPos = Link;\r
- MoveToNextStatement (Selection, FALSE, &NewPos, BottomRow - TopRow);\r
- }\r
- } else {\r
- if (Index >= TopRow) {\r
- //\r
- // At here, only case "Index < PreviousMenuOption->Skip" can reach here.\r
- //\r
- SkipValue = PreviousMenuOption->Skip - (Index - TopRow);\r
- } else {\r
- SkipValue = PreviousMenuOption->Skip - (TopRow - Index);\r
- Link = Link->ForwardLink;\r
- }\r
-\r
- //\r
- // Move to the option in Next page.\r
- //\r
- if (TopOfScreen == &gMenuOption) {\r
- NewPos = gMenuOption.BackLink;\r
- MoveToNextStatement (Selection, TRUE, &NewPos, BottomRow - TopRow);\r
- } else {\r
- NewPos = Link;\r
- MoveToNextStatement (Selection, FALSE, &NewPos, BottomRow - TopRow);\r
- }\r
-\r
- //\r
- // There are more MenuOption needing scrolling up.\r
- //\r
- TopOfScreen = Link;\r
- MenuOption = NULL;\r
- }\r
-\r
- //\r
- // If we encounter a Date/Time op-code set, rewind to the first op-code of the set.\r
- // Don't do this when we are already in the first page.\r
- //\r
- AdjustDateAndTimePosition (TRUE, &TopOfScreen);\r
- AdjustDateAndTimePosition (TRUE, &NewPos);\r
- break;\r
-\r
- case CfUiPageDown:\r
- //\r
- // SkipValue means lines is skipped when show the top menu option.\r
- //\r
- ControlFlag = CfCheckSelection;\r
-\r
- ASSERT (NewPos != NULL);\r
- if (NewPos->ForwardLink == &gMenuOption) {\r
- NewLine = FALSE;\r
- Repaint = FALSE;\r
- break;\r
- }\r
-\r
- NewLine = TRUE;\r
- Repaint = TRUE;\r
- Link = TopOfScreen;\r
- NextMenuOption = MENU_OPTION_FROM_LINK (Link);\r
- Index = TopRow + NextMenuOption->Skip - SkipValue;\r
- //\r
- // Count to the menu option which will show at the top of the next form.\r
- //\r
- while ((Index <= BottomRow + 1) && (Link->ForwardLink != &gMenuOption)) {\r
- Link = Link->ForwardLink;\r
- NextMenuOption = MENU_OPTION_FROM_LINK (Link);\r
- Index = Index + NextMenuOption->Skip;\r
- }\r
-\r
- if ((Link->ForwardLink == &gMenuOption) && (Index <= BottomRow + 1)) {\r
- //\r
- // Finally we know that NewPos is the last MenuOption can be focused.\r
- //\r
- Repaint = FALSE;\r
- MoveToNextStatement (Selection, TRUE, &Link, Index - TopRow);\r
- SkipValue = 0;\r
- } else {\r
- //\r
- // Calculate the skip line for top of screen menu.\r
- //\r
- if (Link == TopOfScreen) {\r
- //\r
- // The top of screen menu option occupies the entire form.\r
- //\r
- SkipValue += BottomRow - TopRow + 1;\r
- } else {\r
- SkipValue = NextMenuOption->Skip - (Index - (BottomRow + 1));\r
- }\r
-\r
- TopOfScreen = Link;\r
- MenuOption = NULL;\r
- //\r
- // Move to the Next selectable menu.\r
- //\r
- MoveToNextStatement (Selection, FALSE, &Link, BottomRow - TopRow);\r
- }\r
-\r
- //\r
- // Save the menu as the next highlight menu.\r
- //\r
- NewPos = Link;\r
-\r
- //\r
- // If we encounter a Date/Time op-code set, rewind to the first op-code of the set.\r
- // Don't do this when we are already in the last page.\r
- //\r
- AdjustDateAndTimePosition (TRUE, &TopOfScreen);\r
- AdjustDateAndTimePosition (TRUE, &NewPos);\r
- break;\r
-\r
- case CfUiDown:\r
- //\r
- // SkipValue means lines is skipped when show the top menu option.\r
- // NewPos points to the menu which is highlighted now.\r
- //\r
- ControlFlag = CfCheckSelection;\r
- //\r
- // Since the behavior of hitting the down arrow on a Date/Time op-code is intended\r
- // to be one that progresses to the next set of op-codes, we need to advance to the last\r
- // Date/Time op-code and leave the remaining logic in UiDown intact so the appropriate\r
- // checking can be done. The only other logic we need to introduce is that if a Date/Time\r
- // op-code is the last entry in the menu, we need to rewind back to the first op-code of\r
- // the Date/Time op-code.\r
- //\r
- SavedListEntry = NewPos;\r
- AdjustDateAndTimePosition (FALSE, &NewPos);\r
-\r
- if (NewPos->ForwardLink != &gMenuOption) {\r
- MenuOption = MENU_OPTION_FROM_LINK (NewPos);\r
- NewLine = TRUE;\r
- NewPos = NewPos->ForwardLink;\r
-\r
- Difference = 0;\r
- //\r
- // Current menu not at the bottom of the form.\r
- //\r
- if (BottomRow >= MenuOption->Row + MenuOption->Skip) {\r
- //\r
- // Find the next selectable menu.\r
- //\r
- Difference = MoveToNextStatement (Selection, FALSE, &NewPos, BottomRow - MenuOption->Row - MenuOption->Skip);\r
- //\r
- // We hit the end of MenuOption that can be focused\r
- // so we simply scroll to the first page.\r
- //\r
- if (Difference < 0) {\r
- //\r
- // Scroll to the first page.\r
- //\r
- if (TopOfScreen != gMenuOption.ForwardLink) {\r
- TopOfScreen = gMenuOption.ForwardLink;\r
- Repaint = TRUE;\r
- MenuOption = NULL;\r
- } else {\r
- MenuOption = MENU_OPTION_FROM_LINK (SavedListEntry);\r
- }\r
- NewPos = gMenuOption.ForwardLink;\r
- MoveToNextStatement (Selection, FALSE, &NewPos, BottomRow - TopRow);\r
-\r
- SkipValue = 0;\r
- //\r
- // If we are at the end of the list and sitting on a Date/Time op, rewind to the head.\r
- //\r
- AdjustDateAndTimePosition (TRUE, &TopOfScreen);\r
- AdjustDateAndTimePosition (TRUE, &NewPos);\r
- break;\r
- }\r
- }\r
- NextMenuOption = MENU_OPTION_FROM_LINK (NewPos);\r
- if (NextMenuOption->Row == 0) {\r
- UpdateOptionSkipLines (Selection, NextMenuOption);\r
- }\r
- DistanceValue = Difference + NextMenuOption->Skip;\r
-\r
- Temp = MenuOption->Row + MenuOption->Skip + DistanceValue - 1;\r
- if ((MenuOption->Row + MenuOption->Skip == BottomRow + 1) &&\r
- (NextMenuOption->ThisTag->Operand == EFI_IFR_DATE_OP ||\r
- NextMenuOption->ThisTag->Operand == EFI_IFR_TIME_OP)\r
- ) {\r
- Temp ++;\r
- }\r
-\r
- //\r
- // If we are going to scroll, update TopOfScreen\r
- //\r
- if (Temp > BottomRow) {\r
- do {\r
- //\r
- // Is the current top of screen a zero-advance op-code?\r
- // If so, keep moving forward till we hit a >0 advance op-code\r
- //\r
- SavedMenuOption = MENU_OPTION_FROM_LINK (TopOfScreen);\r
-\r
- //\r
- // If bottom op-code is more than one line or top op-code is more than one line\r
- //\r
- if ((DistanceValue > 1) || (SavedMenuOption->Skip > 1)) {\r
- //\r
- // Is the bottom op-code greater than or equal in size to the top op-code?\r
- //\r
- if ((Temp - BottomRow) >= (SavedMenuOption->Skip - SkipValue)) {\r
- //\r
- // Skip the top op-code\r
- //\r
- TopOfScreen = TopOfScreen->ForwardLink;\r
- Difference = (Temp - BottomRow) - (SavedMenuOption->Skip - SkipValue);\r
-\r
- SavedMenuOption = MENU_OPTION_FROM_LINK (TopOfScreen);\r
-\r
- //\r
- // If we have a remainder, skip that many more op-codes until we drain the remainder\r
- //\r
- while (Difference >= (INTN) SavedMenuOption->Skip) {\r
- //\r
- // Since the Difference is greater than or equal to this op-code's skip value, skip it\r
- //\r
- Difference = Difference - (INTN) SavedMenuOption->Skip;\r
- TopOfScreen = TopOfScreen->ForwardLink;\r
- SavedMenuOption = MENU_OPTION_FROM_LINK (TopOfScreen);\r
- }\r
- //\r
- // Since we will act on this op-code in the next routine, and increment the\r
- // SkipValue, set the skips to one less than what is required.\r
- //\r
- SkipValue = Difference - 1;\r
- } else {\r
- //\r
- // Since we will act on this op-code in the next routine, and increment the\r
- // SkipValue, set the skips to one less than what is required.\r
- //\r
- SkipValue += (Temp - BottomRow) - 1;\r
- }\r
- } else {\r
- if ((SkipValue + 1) == (INTN) SavedMenuOption->Skip) {\r
- TopOfScreen = TopOfScreen->ForwardLink;\r
- break;\r
- }\r
- }\r
- //\r
- // If the op-code at the top of the screen is more than one line, let's not skip it yet\r
- // Let's set a skip flag to smoothly scroll the top of the screen.\r
- //\r
- if (SavedMenuOption->Skip > 1) {\r
- if (SavedMenuOption == NextMenuOption) {\r
- SkipValue = 0;\r
- } else {\r
- SkipValue++;\r
- }\r
- } else if (SavedMenuOption->Skip == 1) {\r
- SkipValue = 0;\r
- } else {\r
- SkipValue = 0;\r
- TopOfScreen = TopOfScreen->ForwardLink;\r
- }\r
- } while (SavedMenuOption->Skip == 0);\r
-\r
- Repaint = TRUE;\r
- } else if (!IsSelectable (NextMenuOption)) {\r
- //\r
- // Continue to go down until scroll to next page or the selectable option is found.\r
- //\r
- ScreenOperation = UiDown;\r
- ControlFlag = CfScreenOperation;\r
- }\r
-\r
- MenuOption = MENU_OPTION_FROM_LINK (SavedListEntry);\r
-\r
- UpdateStatusBar (Selection, INPUT_ERROR, MenuOption->ThisTag->QuestionFlags, FALSE);\r
-\r
- } else {\r
- //\r
- // Scroll to the first page.\r
- //\r
- if (TopOfScreen != gMenuOption.ForwardLink) {\r
- TopOfScreen = gMenuOption.ForwardLink;\r
- Repaint = TRUE;\r
- MenuOption = NULL;\r
- } else {\r
- //\r
- // Need to remove the current highlight menu.\r
- // MenuOption saved the last highlight menu info.\r
- //\r
- MenuOption = MENU_OPTION_FROM_LINK (SavedListEntry);\r
- }\r
-\r
- SkipValue = 0;\r
- NewLine = TRUE;\r
- //\r
- // Get the next highlight menu.\r
- //\r
- NewPos = gMenuOption.ForwardLink;\r
- MoveToNextStatement (Selection, FALSE, &NewPos, BottomRow - TopRow);\r
- }\r
-\r
- //\r
- // If we are at the end of the list and sitting on a Date/Time op, rewind to the head.\r
- //\r
- AdjustDateAndTimePosition (TRUE, &TopOfScreen);\r
- AdjustDateAndTimePosition (TRUE, &NewPos);\r
- break;\r
-\r
- case CfUiHotKey:\r
- ControlFlag = CfCheckSelection;\r
- \r
- Status = EFI_SUCCESS;\r
- //\r
- // Discard changes. After it, no NV flag is showed.\r
- //\r
- if ((HotKey->Action & BROWSER_ACTION_DISCARD) == BROWSER_ACTION_DISCARD) {\r
- Status = DiscardForm (Selection->FormSet, Selection->Form, gBrowserSettingScope);\r
- if (!EFI_ERROR (Status)) {\r
- Selection->Action = UI_ACTION_REFRESH_FORM;\r
- Selection->Statement = NULL;\r
- gResetRequired = FALSE;\r
- } else {\r
- do {\r
- CreateDialog (4, TRUE, 0, NULL, &Key, HotKey->HelpString, gDiscardFailed, gPressEnter, gEmptyString);\r
- } while (Key.UnicodeChar != CHAR_CARRIAGE_RETURN);\r
- //\r
- // Still show current page.\r
- //\r
- Selection->Action = UI_ACTION_NONE;\r
- Repaint = TRUE;\r
- NewLine = TRUE;\r
- break;\r
- }\r
- }\r
-\r
- //\r
- // Reterieve default setting. After it. NV flag will be showed.\r
- //\r
- if ((HotKey->Action & BROWSER_ACTION_DEFAULT) == BROWSER_ACTION_DEFAULT) {\r
- Status = ExtractDefault (Selection->FormSet, Selection->Form, HotKey->DefaultId, gBrowserSettingScope, GetDefaultForAll, NULL, FALSE);\r
- if (!EFI_ERROR (Status)) {\r
- Selection->Action = UI_ACTION_REFRESH_FORM;\r
- Selection->Statement = NULL;\r
- gResetRequired = TRUE;\r
- } else {\r
- do {\r
- CreateDialog (4, TRUE, 0, NULL, &Key, HotKey->HelpString, gDefaultFailed, gPressEnter, gEmptyString);\r
- } while (Key.UnicodeChar != CHAR_CARRIAGE_RETURN);\r
- //\r
- // Still show current page.\r
- //\r
- Selection->Action = UI_ACTION_NONE;\r
- Repaint = TRUE;\r
- NewLine = TRUE;\r
- break;\r
- }\r
- }\r
-\r
- //\r
- // Save changes. After it, no NV flag is showed.\r
- //\r
- if ((HotKey->Action & BROWSER_ACTION_SUBMIT) == BROWSER_ACTION_SUBMIT) {\r
- Status = SubmitForm (Selection->FormSet, Selection->Form, gBrowserSettingScope);\r
- if (!EFI_ERROR (Status)) {\r
- ASSERT(MenuOption != NULL);\r
- UpdateStatusBar (Selection, INPUT_ERROR, MenuOption->ThisTag->QuestionFlags, FALSE);\r
- UpdateStatusBar (Selection, NV_UPDATE_REQUIRED, MenuOption->ThisTag->QuestionFlags, FALSE);\r
- } else {\r
- do {\r
- CreateDialog (4, TRUE, 0, NULL, &Key, HotKey->HelpString, gSaveFailed, gPressEnter, gEmptyString);\r
- } while (Key.UnicodeChar != CHAR_CARRIAGE_RETURN);\r
- //\r
- // Still show current page.\r
- //\r
- Selection->Action = UI_ACTION_NONE;\r
- Repaint = TRUE;\r
- NewLine = TRUE;\r
- break;\r
- }\r
- }\r
- \r
- //\r
- // Set Reset required Flag\r
- //\r
- if ((HotKey->Action & BROWSER_ACTION_RESET) == BROWSER_ACTION_RESET) {\r
- gResetRequired = TRUE;\r
- }\r
- \r
- //\r
- // Exit Action\r
- //\r
- if ((HotKey->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 (Selection->FormSet, Selection->Form, gBrowserSettingScope);\r
- if (gBrowserSettingScope == FormLevel) {\r
- ControlFlag = CfUiReset;\r
- } else if (gBrowserSettingScope == FormSetLevel) {\r
- Selection->Action = UI_ACTION_EXIT;\r
- } else if (gBrowserSettingScope == SystemLevel) {\r
- if (ExitHandlerFunction != NULL) {\r
- ExitHandlerFunction ();\r
- }\r
- Selection->Action = UI_ACTION_EXIT;\r
- }\r
- Selection->Statement = NULL;\r
- }\r
- break;\r
-\r
- case CfUiDefault:\r
- ControlFlag = CfCheckSelection;\r
- //\r
- // Reset to default value for all forms in the whole system.\r
- //\r
- Status = ExtractDefault (Selection->FormSet, NULL, DefaultId, FormSetLevel, GetDefaultForAll, NULL, FALSE);\r
-\r
- if (!EFI_ERROR (Status)) {\r
- Selection->Action = UI_ACTION_REFRESH_FORM;\r
- Selection->Statement = NULL;\r
- gResetRequired = TRUE;\r
- }\r
- break;\r
-\r
- case CfUiNoOperation:\r
- ControlFlag = CfCheckSelection;\r
- break;\r
-\r
- case CfExit:\r
- UiFreeRefreshList ();\r
-\r
- gST->ConOut->SetAttribute (gST->ConOut, EFI_TEXT_ATTR (EFI_LIGHTGRAY, EFI_BLACK));\r
- gST->ConOut->SetCursorPosition (gST->ConOut, 0, Row + 4);\r
- gST->ConOut->EnableCursor (gST->ConOut, TRUE);\r
- gST->ConOut->OutputString (gST->ConOut, L"\n");\r
- if (HelpString != NULL) {\r
- FreePool (HelpString);\r
- }\r
- if (HelpHeaderString != NULL) {\r
- FreePool (HelpHeaderString);\r
- }\r
- if (HelpBottomString != NULL) {\r
- FreePool (HelpBottomString);\r
- }\r
-\r
- return EFI_SUCCESS;\r
-\r
- default:\r
- break;\r
- }\r
- }\r
-}\r
+++ /dev/null
-/** @file\r
-Private structure, MACRO and function definitions for User Interface related functionalities.\r
-\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
-THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
-WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
-\r
-**/\r
-\r
-#ifndef _UI_H_\r
-#define _UI_H_\r
-\r
-//\r
-// Globals\r
-//\r
-#define REGULAR_NUMERIC 0\r
-#define TIME_NUMERIC 1\r
-#define DATE_NUMERIC 2\r
-\r
-#define SUBTITLE_INDENT 2\r
-\r
-\r
-//\r
-// It take 23 characters including the NULL to print a 64 bits number with "[" and "]".\r
-// pow(2, 64) = [18446744073709551616]\r
-//\r
-#define MAX_NUMERIC_INPUT_WIDTH 23\r
-\r
-typedef enum {\r
- UiNoOperation,\r
- UiSelect,\r
- UiUp,\r
- UiDown,\r
- UiLeft,\r
- UiRight,\r
- UiReset,\r
- UiPrevious,\r
- UiPageUp,\r
- UiPageDown,\r
- UiHotKey,\r
- UiMaxOperation\r
-} UI_SCREEN_OPERATION;\r
-\r
-typedef enum {\r
- CfInitialization,\r
- CfCheckSelection,\r
- CfRepaint,\r
- CfRefreshHighLight,\r
- CfUpdateHelpString,\r
- CfPrepareToReadKey,\r
- CfReadKey,\r
- CfScreenOperation,\r
- CfUiSelect,\r
- CfUiReset,\r
- CfUiLeft,\r
- CfUiRight,\r
- CfUiUp,\r
- CfUiPageUp,\r
- CfUiPageDown,\r
- CfUiDown,\r
- CfUiDefault,\r
- CfUiNoOperation,\r
- CfExit,\r
- CfUiHotKey,\r
- CfMaxControlFlag\r
-} UI_CONTROL_FLAG;\r
-\r
-#define UI_ACTION_NONE 0\r
-#define UI_ACTION_REFRESH_FORM 1\r
-#define UI_ACTION_REFRESH_FORMSET 2\r
-#define UI_ACTION_EXIT 3\r
-\r
-typedef struct _UI_MENU_LIST UI_MENU_LIST;\r
-\r
-typedef struct {\r
- EFI_HII_HANDLE Handle;\r
-\r
- //\r
- // Target formset/form/Question information\r
- //\r
- EFI_GUID FormSetGuid;\r
- UINT16 FormId;\r
- UINT16 QuestionId;\r
- UINTN Sequence; // used for time/date only.\r
-\r
- UINTN TopRow;\r
- UINTN BottomRow;\r
- UINTN PromptCol;\r
- UINTN OptionCol;\r
- UINTN CurrentRow;\r
-\r
- //\r
- // Ation for Browser to taken:\r
- // UI_ACTION_NONE - navigation inside a form\r
- // UI_ACTION_REFRESH_FORM - re-evaluate expressions and repaint form\r
- // UI_ACTION_REFRESH_FORMSET - re-parse formset IFR binary\r
- //\r
- UINTN Action;\r
-\r
- //\r
- // Current selected fomset/form/Question\r
- //\r
- FORM_BROWSER_FORMSET *FormSet;\r
- FORM_BROWSER_FORM *Form;\r
- FORM_BROWSER_STATEMENT *Statement;\r
-\r
- //\r
- // Whether the Form is editable\r
- //\r
- BOOLEAN FormEditable;\r
-\r
- UI_MENU_LIST *CurrentMenu;\r
-} UI_MENU_SELECTION;\r
-\r
-#define UI_MENU_OPTION_SIGNATURE SIGNATURE_32 ('u', 'i', 'm', 'm')\r
-#define UI_MENU_LIST_SIGNATURE SIGNATURE_32 ('u', 'i', 'm', 'l')\r
-\r
-typedef struct {\r
- UINTN Signature;\r
- LIST_ENTRY Link;\r
-\r
- EFI_HII_HANDLE Handle;\r
- FORM_BROWSER_STATEMENT *ThisTag;\r
- UINT16 EntryNumber;\r
-\r
- UINTN Row;\r
- UINTN Col;\r
- UINTN OptCol;\r
- CHAR16 *Description;\r
- UINTN Skip; // Number of lines\r
-\r
- //\r
- // Display item sequence for date/time\r
- // Date: Month/Day/Year\r
- // Sequence: 0 1 2\r
- //\r
- // Time: Hour : Minute : Second\r
- // Sequence: 0 1 2\r
- //\r
- //\r
- UINTN Sequence;\r
-\r
- BOOLEAN GrayOut;\r
- BOOLEAN ReadOnly;\r
-\r
- //\r
- // Whether user could change value of this item\r
- //\r
- BOOLEAN IsQuestion;\r
-} UI_MENU_OPTION;\r
-\r
-#define MENU_OPTION_FROM_LINK(a) CR (a, UI_MENU_OPTION, Link, UI_MENU_OPTION_SIGNATURE)\r
-\r
-struct _UI_MENU_LIST {\r
- UINTN Signature;\r
- LIST_ENTRY Link;\r
-\r
- EFI_HII_HANDLE HiiHandle;\r
- EFI_GUID FormSetGuid;\r
- UINT16 FormId;\r
- UINT16 QuestionId;\r
- UINTN Sequence; // used for time/date only.\r
-\r
- UI_MENU_LIST *Parent;\r
- LIST_ENTRY ChildListHead;\r
-};\r
-\r
-#define UI_MENU_LIST_FROM_LINK(a) CR (a, UI_MENU_LIST, Link, UI_MENU_LIST_SIGNATURE)\r
-\r
-typedef struct _MENU_REFRESH_ENTRY MENU_REFRESH_ENTRY;\r
-struct _MENU_REFRESH_ENTRY {\r
- MENU_REFRESH_ENTRY *Next;\r
- UI_MENU_OPTION *MenuOption; // Describes the entry needing an update\r
- UI_MENU_SELECTION *Selection;\r
- UINTN CurrentColumn;\r
- UINTN CurrentRow;\r
- UINTN CurrentAttribute;\r
- EFI_EVENT Event;\r
-};\r
-\r
-typedef struct {\r
- UINT16 ScanCode;\r
- UI_SCREEN_OPERATION ScreenOperation;\r
-} SCAN_CODE_TO_SCREEN_OPERATION;\r
-\r
-typedef struct {\r
- UI_SCREEN_OPERATION ScreenOperation;\r
- UI_CONTROL_FLAG ControlFlag;\r
-} SCREEN_OPERATION_T0_CONTROL_FLAG;\r
-\r
-\r
-extern LIST_ENTRY gMenuOption;\r
-extern LIST_ENTRY gMenuList;\r
-extern MENU_REFRESH_ENTRY *gMenuRefreshHead;\r
-extern UI_MENU_SELECTION *gCurrentSelection;\r
-extern BOOLEAN mHiiPackageListUpdated;\r
-\r
-//\r
-// Global Functions\r
-//\r
-/**\r
- Initialize Menu option list.\r
-\r
-**/\r
-VOID\r
-UiInitMenu (\r
- VOID\r
- );\r
-\r
-/**\r
- Initialize Menu option list.\r
-\r
-**/\r
-VOID\r
-UiInitMenuList (\r
- VOID\r
- );\r
-\r
-/**\r
- Free Menu option linked list.\r
-\r
-**/\r
-VOID\r
-UiFreeMenu (\r
- VOID\r
- );\r
-\r
-/**\r
- Create a menu with specified formset GUID and form ID, and add it as a child\r
- of the given parent menu.\r
-\r
- @param Parent The parent of menu to be added.\r
- @param HiiHandle Hii handle related to this formset.\r
- @param FormSetGuid The Formset Guid of menu to be added.\r
- @param FormId The Form ID of menu to be added.\r
-\r
- @return A pointer to the newly added menu or NULL if memory is insufficient.\r
-\r
-**/\r
-UI_MENU_LIST *\r
-UiAddMenuList (\r
- IN OUT UI_MENU_LIST *Parent,\r
- IN EFI_HII_HANDLE HiiHandle,\r
- IN EFI_GUID *FormSetGuid,\r
- IN UINT16 FormId\r
- );\r
-\r
-/**\r
- Search Menu with given FormId, FormSetGuid and Handle in all cached menu list.\r
-\r
- @param Parent The parent of menu to search.\r
- @param Handle Hii handle related to this formset.\r
- @param FormSetGuid The Formset GUID of the menu to search. \r
- @param FormId The Form ID of menu to search.\r
-\r
- @return A pointer to menu found or NULL if not found.\r
-\r
-**/\r
-UI_MENU_LIST *\r
-UiFindChildMenuList (\r
- IN UI_MENU_LIST *Parent,\r
- IN EFI_HII_HANDLE Handle,\r
- IN EFI_GUID *FormSetGuid, \r
- IN UINT16 FormId\r
- );\r
-\r
-/**\r
- Search Menu with given Handle, FormSetGuid and FormId in all cached menu list.\r
-\r
- @param Handle Hii handle related to this formset.\r
- @param FormSetGuid The Formset GUID of the menu to search.\r
- @param FormId The Form ID of menu to search.\r
-\r
- @return A pointer to menu found or NULL if not found.\r
-\r
-**/\r
-UI_MENU_LIST *\r
-UiFindMenuList (\r
- IN EFI_HII_HANDLE Handle,\r
- IN EFI_GUID *FormSetGuid,\r
- IN UINT16 FormId\r
- );\r
-\r
-/**\r
- Free Menu list linked list.\r
-\r
- @param MenuListHead One Menu list point in the menu list.\r
-\r
-**/\r
-VOID\r
-UiFreeMenuList (\r
- LIST_ENTRY *MenuListHead\r
- );\r
-\r
-/**\r
- Free Menu option linked list.\r
-\r
-**/\r
-VOID\r
-UiFreeRefreshList (\r
- VOID\r
- );\r
-\r
-/**\r
- Add one menu option by specified description and context.\r
-\r
- @param String String description for this option.\r
- @param Handle Hii handle for the package list.\r
- @param Form The form this statement belong to.\r
- @param Statement Statement of this Menu Option.\r
- @param NumberOfLines Display lines for this Menu Option.\r
- @param MenuItemCount The index for this Option in the Menu.\r
-\r
- @retval Pointer Pointer to the added Menu Option.\r
-\r
-**/\r
-UI_MENU_OPTION *\r
-UiAddMenuOption (\r
- IN CHAR16 *String,\r
- IN EFI_HII_HANDLE Handle,\r
- IN FORM_BROWSER_FORM *Form,\r
- IN FORM_BROWSER_STATEMENT *Statement,\r
- IN UINT16 NumberOfLines,\r
- IN UINT16 MenuItemCount\r
- );\r
-\r
-/**\r
- Display menu and wait for user to select one menu option, then return it.\r
- If AutoBoot is enabled, then if user doesn't select any option,\r
- after period of time, it will automatically return the first menu option.\r
-\r
- @param Selection Menu selection.\r
-\r
- @return Return the pointer of the menu which selected,\r
- @return otherwise return NULL.\r
-\r
-**/\r
-EFI_STATUS\r
-UiDisplayMenu (\r
- IN OUT UI_MENU_SELECTION *Selection\r
- );\r
-\r
-/**\r
- Free up the resource allocated for all strings required\r
- by Setup Browser.\r
-\r
-**/\r
-VOID\r
-FreeBrowserStrings (\r
- VOID\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
- @param Repaint Whether need to repaint the menu.\r
- @param NewLine Whether need to create new line.\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
- OUT BOOLEAN *Repaint,\r
- OUT BOOLEAN *NewLine\r
- );\r
-\r
-\r
-/**\r
- The worker function that send the displays to the screen. On output,\r
- the selection made by user is returned.\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
- @retval EFI_SUCCESS The page is displayed successfully.\r
- @return Other value if the page failed to be diplayed.\r
-\r
-**/\r
-EFI_STATUS\r
-SetupBrowser (\r
- IN OUT UI_MENU_SELECTION *Selection\r
- );\r
-\r
-/**\r
- Set Buffer to Value for Size bytes.\r
-\r
- @param Buffer Memory to set.\r
- @param Size Number of bytes to set\r
- @param Value Value of the set operation.\r
-\r
-**/\r
-VOID\r
-SetUnicodeMem (\r
- IN VOID *Buffer,\r
- IN UINTN Size,\r
- IN CHAR16 Value\r
- );\r
-\r
-/**\r
- Wait for a given event to fire, or for an optional timeout to expire.\r
-\r
- @param Event The event to wait for\r
- @param Timeout An optional timeout value in 100 ns units.\r
- @param RefreshInterval Menu refresh interval (in seconds).\r
-\r
- @retval EFI_SUCCESS Event fired before Timeout expired.\r
- @retval EFI_TIME_OUT Timout expired before Event fired.\r
-\r
-**/\r
-EFI_STATUS\r
-UiWaitForSingleEvent (\r
- IN EFI_EVENT Event,\r
- IN UINT64 Timeout, OPTIONAL\r
- IN UINT8 RefreshInterval OPTIONAL\r
- );\r
-\r
-/**\r
- Draw a pop up windows based on the dimension, number of lines and\r
- strings specified.\r
-\r
- @param ScreenWidth The width of the pop-up.\r
- @param NumberOfLines The number of lines.\r
- @param ... A series of text strings that displayed in the pop-up.\r
-\r
-**/\r
-VOID\r
-EFIAPI\r
-CreateMultiStringPopUp (\r
- IN UINTN ScreenWidth,\r
- IN UINTN NumberOfLines,\r
- ...\r
- );\r
-\r
-/**\r
- Get string or password input from user.\r
-\r
- @param MenuOption Pointer to the current input menu.\r
- @param Prompt The prompt string shown on popup window.\r
- @param StringPtr Old user input and destination for use input string.\r
-\r
- @retval EFI_SUCCESS If string input is read successfully\r
- @retval EFI_DEVICE_ERROR If operation fails\r
-\r
-**/\r
-EFI_STATUS\r
-ReadString (\r
- IN UI_MENU_OPTION *MenuOption,\r
- IN CHAR16 *Prompt,\r
- IN OUT CHAR16 *StringPtr\r
- );\r
-\r
-/**\r
- Get selection for OneOf and OrderedList (Left/Right will be ignored).\r
-\r
- @param Selection Pointer to current selection.\r
- @param MenuOption Pointer to the current input menu.\r
-\r
- @retval EFI_SUCCESS If Option input is processed successfully\r
- @retval EFI_DEVICE_ERROR If operation fails\r
-\r
-**/\r
-EFI_STATUS\r
-GetSelectionInputPopUp (\r
- IN UI_MENU_SELECTION *Selection,\r
- IN UI_MENU_OPTION *MenuOption\r
- );\r
-\r
-/**\r
- This routine reads a numeric value from the user input.\r
-\r
- @param Selection Pointer to current selection.\r
- @param MenuOption Pointer to the current input menu.\r
-\r
- @retval EFI_SUCCESS If numerical input is read successfully\r
- @retval EFI_DEVICE_ERROR If operation fails\r
-\r
-**/\r
-EFI_STATUS\r
-GetNumericInput (\r
- IN UI_MENU_SELECTION *Selection,\r
- IN UI_MENU_OPTION *MenuOption\r
- );\r
-\r
-/**\r
- Update status bar on the bottom of menu.\r
-\r
- @param Selection Current selection info.\r
- @param MessageType The type of message to be shown.\r
- @param Flags The flags in Question header.\r
- @param State Set or clear.\r
-\r
-**/\r
-VOID\r
-UpdateStatusBar (\r
- IN UI_MENU_SELECTION *Selection,\r
- IN UINTN MessageType,\r
- IN UINT8 Flags,\r
- IN BOOLEAN State\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
-/**\r
- Print Question Value according to it's storage width and display attributes.\r
-\r
- @param Question The Question to be printed.\r
- @param FormattedNumber Buffer for output string.\r
- @param BufferSize The FormattedNumber buffer size in bytes.\r
-\r
- @retval EFI_SUCCESS Print success.\r
- @retval EFI_BUFFER_TOO_SMALL Buffer size is not enough for formatted number.\r
-\r
-**/\r
-EFI_STATUS\r
-PrintFormattedNumber (\r
- IN FORM_BROWSER_STATEMENT *Question,\r
- IN OUT CHAR16 *FormattedNumber,\r
- IN UINTN BufferSize\r
- );\r
-\r
-/**\r
- Search an Option of a Question by its value.\r
-\r
- @param Question The Question\r
- @param OptionValue Value for Option to be searched.\r
-\r
- @retval Pointer Pointer to the found Option.\r
- @retval NULL Option not found.\r
-\r
-**/\r
-QUESTION_OPTION *\r
-ValueToOption (\r
- IN FORM_BROWSER_STATEMENT *Question,\r
- IN EFI_HII_VALUE *OptionValue\r
- );\r
-\r
-/**\r
- Return data element in an Array by its Index.\r
-\r
- @param Array The data array.\r
- @param Type Type of the data in this array.\r
- @param Index Zero based index for data in this array.\r
-\r
- @retval Value The data to be returned\r
-\r
-**/\r
-UINT64\r
-GetArrayData (\r
- IN VOID *Array,\r
- IN UINT8 Type,\r
- IN UINTN Index\r
- );\r
-\r
-/**\r
- Set value of a data element in an Array by its Index.\r
-\r
- @param Array The data array.\r
- @param Type Type of the data in this array.\r
- @param Index Zero based index for data in this array.\r
- @param Value The value to be set.\r
-\r
-**/\r
-VOID\r
-SetArrayData (\r
- IN VOID *Array,\r
- IN UINT8 Type,\r
- IN UINTN Index,\r
- IN UINT64 Value\r
- );\r
-\r
-/**\r
- Check whether this value already in the array, if yes, return the index.\r
-\r
- @param Array The data array.\r
- @param Type Type of the data in this array.\r
- @param Value The value to be find.\r
- @param Index The index in the array which has same value with Value.\r
- \r
- @retval TRUE Found the value in the array.\r
- @retval FALSE Not found the value.\r
-\r
-**/\r
-BOOLEAN \r
-FindArrayData (\r
- IN VOID *Array,\r
- IN UINT8 Type,\r
- IN UINT64 Value,\r
- OUT UINTN *Index OPTIONAL\r
- );\r
-\r
-/**\r
- Process a Question's Option (whether selected or un-selected).\r
-\r
- @param Selection Pointer to UI_MENU_SELECTION.\r
- @param MenuOption The MenuOption for this Question.\r
- @param Selected TRUE: if Question is selected.\r
- @param OptionString Pointer of the Option String to be displayed.\r
-\r
- @retval EFI_SUCCESS Question Option process success.\r
- @retval Other Question Option process fail.\r
-\r
-**/\r
-EFI_STATUS\r
-ProcessOptions (\r
- IN UI_MENU_SELECTION *Selection,\r
- IN UI_MENU_OPTION *MenuOption,\r
- IN BOOLEAN Selected,\r
- OUT CHAR16 **OptionString\r
- );\r
-\r
-/**\r
- Process the help string: Split StringPtr to several lines of strings stored in\r
- FormattedString and the glyph width of each line cannot exceed gHelpBlockWidth.\r
-\r
- @param StringPtr The entire help string.\r
- @param FormattedString The oupput formatted string.\r
- @param EachLineWidth The string length of each line in the formatted string.\r
- @param RowCount TRUE: if Question is selected.\r
-\r
-**/\r
-UINTN\r
-ProcessHelpString (\r
- IN CHAR16 *StringPtr,\r
- OUT CHAR16 **FormattedString,\r
- OUT UINT16 *EachLineWidth,\r
- IN UINTN RowCount\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
-**/\r
-VOID\r
-UpdateKeyHelp (\r
- IN UI_MENU_SELECTION *Selection,\r
- IN UI_MENU_OPTION *MenuOption,\r
- IN BOOLEAN Selected\r
- );\r
-\r
-/**\r
- Clear retangle with specified text attribute.\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
-\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
- );\r
-\r
-/**\r
- Count the storage space of a Unicode string.\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
-\r
- If String is NULL, then ASSERT ().\r
-\r
- @param String The input string to be counted.\r
-\r
- @return Storage space for the input string.\r
-\r
-**/\r
-UINTN\r
-GetStringWidth (\r
- IN CHAR16 *String\r
- );\r
-\r
-/**\r
- Will copy LineWidth amount of a string in the OutputString buffer and return the\r
- number of CHAR16 characters that were copied into the OutputString buffer.\r
- In the code, it deals \r,\n,\r\n same as \n\r, also it not process the \r or \g.\r
-\r
- @param InputString String description for this option.\r
- @param LineWidth Width of the desired string to extract in CHAR16\r
- characters\r
- @param GlyphWidth The glyph width of the beging char in the string.\r
- @param Index Where in InputString to start the copy process\r
- @param OutputString Buffer to copy the string into\r
-\r
- @return Returns the number of CHAR16 characters that were copied into the OutputString buffer.\r
-\r
-**/\r
-UINT16\r
-GetLineByWidth (\r
- IN CHAR16 *InputString,\r
- IN UINT16 LineWidth,\r
- IN OUT UINT16 *GlyphWidth,\r
- IN OUT UINTN *Index,\r
- OUT CHAR16 **OutputString\r
- );\r
-\r
-/**\r
- Get the supported width for a particular op-code\r
-\r
- @param Statement The FORM_BROWSER_STATEMENT structure passed in.\r
- @param Handle The handle in the HII database being used\r
-\r
- @return Returns the number of CHAR16 characters that is support.\r
-\r
-**/\r
-UINT16\r
-GetWidth (\r
- IN FORM_BROWSER_STATEMENT *Statement,\r
- IN EFI_HII_HANDLE Handle\r
- );\r
-\r
-/**\r
- Concatenate a narrow string to another string.\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
-\r
-**/\r
-VOID\r
-NewStrCat (\r
- IN OUT CHAR16 *Destination,\r
- IN CHAR16 *Source\r
- );\r
-\r
-/**\r
- Wait for a key to be pressed by user.\r
-\r
- @param Key The key which is pressed by user.\r
-\r
- @retval EFI_SUCCESS The function always completed successfully.\r
-\r
-**/\r
-EFI_STATUS\r
-WaitForKeyStroke (\r
- OUT EFI_INPUT_KEY *Key\r
- );\r
-\r
-/**\r
- Reset stack pointer to begin of the stack.\r
-\r
-**/\r
-VOID\r
-ResetScopeStack (\r
- VOID\r
- );\r
-\r
-/**\r
- Push the expression options onto the Stack.\r
-\r
- @param Pointer Pointer to the current expression.\r
- @param Level Which type this expression belong to. Form, \r
- statement or option?\r
-\r
- @retval EFI_SUCCESS The value was pushed onto the stack.\r
- @retval EFI_OUT_OF_RESOURCES There is not enough system memory to grow the stack.\r
-\r
-**/\r
-EFI_STATUS\r
-PushConditionalExpression (\r
- IN FORM_EXPRESSION *Pointer,\r
- IN EXPRESS_LEVEL Level\r
- );\r
-\r
-/**\r
- Pop the expression options from the Stack\r
-\r
- @param Level Which type this expression belong to. Form, \r
- statement or option?\r
-\r
- @retval EFI_SUCCESS The value was pushed onto the stack.\r
- @retval EFI_OUT_OF_RESOURCES There is not enough system memory to grow the stack.\r
-\r
-**/\r
-EFI_STATUS\r
-PopConditionalExpression (\r
- IN EXPRESS_LEVEL Level\r
- );\r
- \r
-/**\r
- Get the expression Buffer pointer.\r
- \r
- @param Level Which type this expression belong to. Form, \r
- statement or option?\r
-\r
- @retval The start pointer of the expression buffer or NULL.\r
-\r
-**/\r
-FORM_EXPRESSION **\r
-GetConditionalExpressionList (\r
- IN EXPRESS_LEVEL Level\r
- );\r
-\r
-/**\r
- Get the expression list count.\r
- \r
- @param Level Which type this expression belong to. Form, \r
- statement or option?\r
-\r
- @retval >=0 The expression count\r
- @retval -1 Input parameter error.\r
-\r
-**/\r
-INTN \r
-GetConditionalExpressionCount (\r
- IN EXPRESS_LEVEL Level\r
- );\r
-\r
-/**\r
- Push an Operand onto the Stack\r
-\r
- @param Operand Operand to push.\r
-\r
- @retval EFI_SUCCESS The value was pushed onto the stack.\r
- @retval EFI_OUT_OF_RESOURCES There is not enough system memory to grow the\r
- stack.\r
-\r
-**/\r
-EFI_STATUS\r
-PushScope (\r
- IN UINT8 Operand\r
- );\r
-\r
-/**\r
- Pop an Operand from the Stack\r
-\r
- @param Operand Operand to pop.\r
-\r
- @retval EFI_SUCCESS The value was pushed onto the stack.\r
- @retval EFI_OUT_OF_RESOURCES There is not enough system memory to grow the\r
- stack.\r
-\r
-**/\r
-EFI_STATUS\r
-PopScope (\r
- OUT UINT8 *Operand\r
- );\r
-\r
-/**\r
- Reset stack pointer to begin of the stack.\r
-\r
-**/\r
-VOID\r
-ResetCurrentExpressionStack (\r
- VOID\r
- );\r
-\r
-/**\r
- Push current expression onto the Stack\r
-\r
- @param Pointer Pointer to current expression.\r
-\r
- @retval EFI_SUCCESS The value was pushed onto the stack.\r
- @retval EFI_OUT_OF_RESOURCES There is not enough system memory to grow the stack.\r
-\r
-**/\r
-EFI_STATUS\r
-PushCurrentExpression (\r
- IN VOID *Pointer\r
- );\r
-\r
-/**\r
- Pop current expression from the Stack\r
-\r
- @param Pointer Pointer to current expression to be pop.\r
-\r
- @retval EFI_SUCCESS The value was pushed onto the stack.\r
- @retval EFI_OUT_OF_RESOURCES There is not enough system memory to grow the stack.\r
-\r
-**/\r
-EFI_STATUS\r
-PopCurrentExpression (\r
- OUT VOID **Pointer\r
- );\r
-\r
-/**\r
- Reset stack pointer to begin of the stack.\r
-\r
-**/\r
-VOID\r
-ResetMapExpressionListStack (\r
- VOID\r
- );\r
-\r
-/**\r
- Push the list of map expression onto the Stack\r
-\r
- @param Pointer Pointer to the list of map expression to be pushed.\r
-\r
- @retval EFI_SUCCESS The value was pushed onto the stack.\r
- @retval EFI_OUT_OF_RESOURCES There is not enough system memory to grow the stack.\r
-\r
-**/\r
-EFI_STATUS\r
-PushMapExpressionList (\r
- IN VOID *Pointer\r
- );\r
-\r
-/**\r
- Pop the list of map expression from the Stack\r
-\r
- @param Pointer Pointer to the list of map expression to be pop.\r
-\r
- @retval EFI_SUCCESS The value was pushed onto the stack.\r
- @retval EFI_OUT_OF_RESOURCES There is not enough system memory to grow the stack.\r
-\r
-**/\r
-EFI_STATUS\r
-PopMapExpressionList (\r
- OUT VOID **Pointer\r
- );\r
-\r
-/**\r
- Get Form given its FormId.\r
-\r
- @param FormSet The formset which contains this form.\r
- @param FormId Id of this form.\r
-\r
- @retval Pointer The form.\r
- @retval NULL Specified Form is not found in the formset.\r
-\r
-**/\r
-FORM_BROWSER_FORM *\r
-IdToForm (\r
- IN FORM_BROWSER_FORMSET *FormSet,\r
- IN UINT16 FormId\r
- );\r
-\r
-/**\r
- Search a Question in Formset scope using its QuestionId.\r
-\r
- @param FormSet The formset which contains this form.\r
- @param Form The form which contains this Question.\r
- @param QuestionId Id of this Question.\r
-\r
- @retval Pointer The Question.\r
- @retval NULL Specified Question not found in the form.\r
-\r
-**/\r
-FORM_BROWSER_STATEMENT *\r
-IdToQuestion (\r
- IN FORM_BROWSER_FORMSET *FormSet,\r
- IN FORM_BROWSER_FORM *Form,\r
- IN UINT16 QuestionId\r
- );\r
-\r
-/**\r
- Zero extend integer/boolean/date/time to UINT64 for comparing.\r
-\r
- @param Value HII Value to be converted.\r
-\r
-**/\r
-VOID\r
-ExtendValueToU64 (\r
- IN EFI_HII_VALUE *Value\r
- );\r
-\r
-/**\r
- Compare two Hii value.\r
-\r
- @param Value1 Expression value to compare on left-hand.\r
- @param Value2 Expression value to compare on right-hand.\r
- @param Result Return value after compare.\r
- retval 0 Two operators equal.\r
- return Positive value if Value1 is greater than Value2.\r
- retval Negative value if Value1 is less than Value2.\r
- @param HiiHandle Only required for string compare.\r
-\r
- @retval other Could not perform compare on two values.\r
- @retval EFI_SUCCESS Compare the value success.\r
-\r
-**/\r
-EFI_STATUS\r
-CompareHiiValue (\r
- IN EFI_HII_VALUE *Value1,\r
- IN EFI_HII_VALUE *Value2,\r
- OUT INTN *Result,\r
- IN EFI_HII_HANDLE HiiHandle OPTIONAL\r
- );\r
-\r
-/**\r
- Evaluate the result of a HII expression\r
-\r
- If Expression is NULL, then ASSERT.\r
-\r
- @param FormSet FormSet associated with this expression.\r
- @param Form Form associated with this expression.\r
- @param Expression Expression to be evaluated.\r
-\r
- @retval EFI_SUCCESS The expression evaluated successfuly\r
- @retval EFI_NOT_FOUND The Question which referenced by a QuestionId\r
- could not be found.\r
- @retval EFI_OUT_OF_RESOURCES There is not enough system memory to grow the\r
- stack.\r
- @retval EFI_ACCESS_DENIED The pop operation underflowed the stack\r
- @retval EFI_INVALID_PARAMETER Syntax error with the Expression\r
-\r
-**/\r
-EFI_STATUS\r
-EvaluateExpression (\r
- IN FORM_BROWSER_FORMSET *FormSet,\r
- IN FORM_BROWSER_FORM *Form,\r
- IN OUT FORM_EXPRESSION *Expression\r
- );\r
-\r
-/**\r
- Return the result of the expression list. Check the expression list and \r
- return the highest priority express result. \r
- Priority: DisableIf > SuppressIf > GrayOutIf > FALSE\r
-\r
- @param ExpList The input expression list.\r
- @param Evaluate Whether need to evaluate the expression first.\r
- @param FormSet FormSet associated with this expression. Only \r
- needed when Evaluate is TRUE\r
- @param Form Form associated with this expression. Only \r
- needed when Evaluate is TRUE \r
-\r
- @retval EXPRESS_RESULT Return the higher priority express result. \r
- DisableIf > SuppressIf > GrayOutIf > FALSE\r
-\r
-**/\r
-EXPRESS_RESULT \r
-EvaluateExpressionList (\r
- IN FORM_EXPRESSION_LIST *ExpList,\r
- IN BOOLEAN Evaluate,\r
- IN FORM_BROWSER_FORMSET *FormSet, OPTIONAL\r
- IN FORM_BROWSER_FORM *Form OPTIONAL\r
- );\r
-\r
-#endif // _UI_H\r
DpcLib|MdeModulePkg/Library/DxeDpcLib/DxeDpcLib.inf\r
OemHookStatusCodeLib|MdeModulePkg/Library/OemHookStatusCodeLibNull/OemHookStatusCodeLibNull.inf\r
GenericBdsLib|IntelFrameworkModulePkg/Library/GenericBdsLib/GenericBdsLib.inf\r
+ CustomizedDisplayLib|MdeModulePkg/Library/CustomizedDisplayLib/CustomizedDisplayLib.inf\r
SecurityManagementLib|MdeModulePkg/Library/DxeSecurityManagementLib/DxeSecurityManagementLib.inf\r
TimerLib|MdePkg/Library/BaseTimerLibNullTemplate/BaseTimerLibNullTemplate.inf\r
SerialPortLib|MdePkg/Library/BaseSerialPortLibNull/BaseSerialPortLibNull.inf\r
\r
IntelFrameworkModulePkg/Universal/BdsDxe/BdsDxe.inf\r
MdeModulePkg/Universal/HiiDatabaseDxe/HiiDatabaseDxe.inf\r
+ MdeModulePkg/Universal/DisplayEngineDxe/DisplayEngineDxe.inf\r
MdeModulePkg/Universal/SetupBrowserDxe/SetupBrowserDxe.inf\r
MdeModulePkg/Universal/PrintDxe/PrintDxe.inf\r
MdeModulePkg/Universal/DriverSampleDxe/DriverSampleDxe.inf {\r
INF MdeModulePkg/Universal/DevicePathDxe/DevicePathDxe.inf\r
INF MdeModulePkg/Universal/Disk/DiskIoDxe/DiskIoDxe.inf\r
INF MdeModulePkg/Universal/Disk/PartitionDxe/PartitionDxe.inf\r
+INF MdeModulePkg/Universal/DisplayEngineDxe/DisplayEngineDxe.inf\r
INF MdeModulePkg/Universal/SetupBrowserDxe/SetupBrowserDxe.inf\r
INF MdeModulePkg/Universal/PrintDxe/PrintDxe.inf\r
INF RuleOverride = TIANOCOMPRESSED MdeModulePkg/Universal/Disk/UnicodeCollation/EnglishDxe/EnglishDxe.inf\r
VirtioLib|OvmfPkg/Library/VirtioLib/VirtioLib.inf\r
LoadLinuxLib|OvmfPkg/Library/LoadLinuxLib/LoadLinuxLib.inf\r
LockBoxLib|MdeModulePkg/Library/LockBoxNullLib/LockBoxNullLib.inf\r
+ CustomizedDisplayLib|MdeModulePkg/Library/CustomizedDisplayLib/CustomizedDisplayLib.inf\r
\r
!ifdef $(SOURCE_DEBUG_ENABLE)\r
PeCoffExtraActionLib|SourceLevelDebugPkg/Library/PeCoffExtraActionLibDebug/PeCoffExtraActionLibDebug.inf\r
PcAtChipsetPkg/Bus/Pci/IdeControllerDxe/IdeControllerDxe.inf\r
MdeModulePkg/Universal/HiiDatabaseDxe/HiiDatabaseDxe.inf\r
MdeModulePkg/Universal/SetupBrowserDxe/SetupBrowserDxe.inf\r
+ MdeModulePkg/Universal/DisplayEngineDxe/DisplayEngineDxe.inf\r
MdeModulePkg/Universal/MemoryTest/NullMemoryTestDxe/NullMemoryTestDxe.inf\r
\r
OvmfPkg/QemuVideoDxe/QemuVideoDxe.inf {\r
INF PcAtChipsetPkg/Bus/Pci/IdeControllerDxe/IdeControllerDxe.inf\r
INF MdeModulePkg/Universal/HiiDatabaseDxe/HiiDatabaseDxe.inf\r
INF MdeModulePkg/Universal/SetupBrowserDxe/SetupBrowserDxe.inf\r
+INF MdeModulePkg/Universal/DisplayEngineDxe/DisplayEngineDxe.inf\r
INF MdeModulePkg/Universal/MemoryTest/NullMemoryTestDxe/NullMemoryTestDxe.inf\r
\r
INF PcAtChipsetPkg/IsaAcpiDxe/IsaAcpi.inf\r
VirtioLib|OvmfPkg/Library/VirtioLib/VirtioLib.inf\r
LoadLinuxLib|OvmfPkg/Library/LoadLinuxLib/LoadLinuxLib.inf\r
LockBoxLib|MdeModulePkg/Library/LockBoxNullLib/LockBoxNullLib.inf\r
+ CustomizedDisplayLib|MdeModulePkg/Library/CustomizedDisplayLib/CustomizedDisplayLib.inf\r
\r
!ifdef $(SOURCE_DEBUG_ENABLE)\r
PeCoffExtraActionLib|SourceLevelDebugPkg/Library/PeCoffExtraActionLibDebug/PeCoffExtraActionLibDebug.inf\r
PcAtChipsetPkg/Bus/Pci/IdeControllerDxe/IdeControllerDxe.inf\r
MdeModulePkg/Universal/HiiDatabaseDxe/HiiDatabaseDxe.inf\r
MdeModulePkg/Universal/SetupBrowserDxe/SetupBrowserDxe.inf\r
+ MdeModulePkg/Universal/DisplayEngineDxe/DisplayEngineDxe.inf\r
MdeModulePkg/Universal/MemoryTest/NullMemoryTestDxe/NullMemoryTestDxe.inf\r
\r
OvmfPkg/QemuVideoDxe/QemuVideoDxe.inf {\r
INF PcAtChipsetPkg/Bus/Pci/IdeControllerDxe/IdeControllerDxe.inf\r
INF MdeModulePkg/Universal/HiiDatabaseDxe/HiiDatabaseDxe.inf\r
INF MdeModulePkg/Universal/SetupBrowserDxe/SetupBrowserDxe.inf\r
+INF MdeModulePkg/Universal/DisplayEngineDxe/DisplayEngineDxe.inf\r
INF MdeModulePkg/Universal/MemoryTest/NullMemoryTestDxe/NullMemoryTestDxe.inf\r
\r
INF PcAtChipsetPkg/IsaAcpiDxe/IsaAcpi.inf\r
VirtioLib|OvmfPkg/Library/VirtioLib/VirtioLib.inf\r
LoadLinuxLib|OvmfPkg/Library/LoadLinuxLib/LoadLinuxLib.inf\r
LockBoxLib|MdeModulePkg/Library/LockBoxNullLib/LockBoxNullLib.inf\r
+ CustomizedDisplayLib|MdeModulePkg/Library/CustomizedDisplayLib/CustomizedDisplayLib.inf\r
\r
!ifdef $(SOURCE_DEBUG_ENABLE)\r
PeCoffExtraActionLib|SourceLevelDebugPkg/Library/PeCoffExtraActionLibDebug/PeCoffExtraActionLibDebug.inf\r
PcAtChipsetPkg/Bus/Pci/IdeControllerDxe/IdeControllerDxe.inf\r
MdeModulePkg/Universal/HiiDatabaseDxe/HiiDatabaseDxe.inf\r
MdeModulePkg/Universal/SetupBrowserDxe/SetupBrowserDxe.inf\r
+ MdeModulePkg/Universal/DisplayEngineDxe/DisplayEngineDxe.inf\r
MdeModulePkg/Universal/MemoryTest/NullMemoryTestDxe/NullMemoryTestDxe.inf\r
\r
OvmfPkg/QemuVideoDxe/QemuVideoDxe.inf {\r
INF PcAtChipsetPkg/Bus/Pci/IdeControllerDxe/IdeControllerDxe.inf\r
INF MdeModulePkg/Universal/HiiDatabaseDxe/HiiDatabaseDxe.inf\r
INF MdeModulePkg/Universal/SetupBrowserDxe/SetupBrowserDxe.inf\r
+INF MdeModulePkg/Universal/DisplayEngineDxe/DisplayEngineDxe.inf\r
INF MdeModulePkg/Universal/MemoryTest/NullMemoryTestDxe/NullMemoryTestDxe.inf\r
\r
INF PcAtChipsetPkg/IsaAcpiDxe/IsaAcpi.inf\r