From: Eric Dong Date: Mon, 12 Aug 2013 02:03:10 +0000 (+0000) Subject: Rollback patch 14537 & 14538, because patch 14537 is not tested by Laszlo Ersek,... X-Git-Tag: edk2-stable201903~12367 X-Git-Url: https://git.proxmox.com/?p=mirror_edk2.git;a=commitdiff_plain;h=253616154506e17ebd02c076f240748f57e36ac2 Rollback patch 14537 & 14538, because patch 14537 is not tested by Laszlo Ersek, but i wrote it. Signed-off-by: Eric Dong git-svn-id: https://svn.code.sf.net/p/edk2/code/trunk/edk2@14539 6f19259b-4bc3-4df7-8a09-765794883524 --- diff --git a/DuetPkg/DuetPkg.fdf b/DuetPkg/DuetPkg.fdf index 66f8b68ed8..f6bcdd9fdb 100644 --- a/DuetPkg/DuetPkg.fdf +++ b/DuetPkg/DuetPkg.fdf @@ -59,7 +59,6 @@ INF MdeModulePkg/Universal/Console/ConPlatformDxe/ConPlatformDxe.inf INF MdeModulePkg/Universal/Console/ConSplitterDxe/ConSplitterDxe.inf INF MdeModulePkg/Universal/HiiDatabaseDxe/HiiDatabaseDxe.inf INF MdeModulePkg/Universal/SetupBrowserDxe/SetupBrowserDxe.inf -INF MdeModulePkg/Universal/DisplayEngineDxe/DisplayEngineDxe.inf INF MdeModulePkg/Universal/Console/GraphicsConsoleDxe/GraphicsConsoleDxe.inf INF MdeModulePkg/Universal/Console/TerminalDxe/TerminalDxe.inf diff --git a/DuetPkg/DuetPkgIa32.dsc b/DuetPkg/DuetPkgIa32.dsc index 117bffb0ec..b35ba913ff 100644 --- a/DuetPkg/DuetPkgIa32.dsc +++ b/DuetPkg/DuetPkgIa32.dsc @@ -85,7 +85,6 @@ SecurityManagementLib|MdeModulePkg/Library/DxeSecurityManagementLib/DxeSecurityManagementLib.inf CapsuleLib|MdeModulePkg/Library/DxeCapsuleLibNull/DxeCapsuleLibNull.inf PeCoffExtraActionLib|MdePkg/Library/BasePeCoffExtraActionLibNull/BasePeCoffExtraActionLibNull.inf - CustomizedDisplayLib|MdeModulePkg/Library/CustomizedDisplayLib/CustomizedDisplayLib.inf # # Platform # @@ -192,7 +191,6 @@ } MdeModulePkg/Universal/HiiDatabaseDxe/HiiDatabaseDxe.inf MdeModulePkg/Universal/SetupBrowserDxe/SetupBrowserDxe.inf - MdeModulePkg/Universal/DisplayEngineDxe/DisplayEngineDxe.inf MdeModulePkg/Universal/Console/GraphicsConsoleDxe/GraphicsConsoleDxe.inf MdeModulePkg/Universal/Console/TerminalDxe/TerminalDxe.inf diff --git a/DuetPkg/DuetPkgX64.dsc b/DuetPkg/DuetPkgX64.dsc index 70b159dd82..65c0d14019 100644 --- a/DuetPkg/DuetPkgX64.dsc +++ b/DuetPkg/DuetPkgX64.dsc @@ -85,7 +85,6 @@ SecurityManagementLib|MdeModulePkg/Library/DxeSecurityManagementLib/DxeSecurityManagementLib.inf CapsuleLib|MdeModulePkg/Library/DxeCapsuleLibNull/DxeCapsuleLibNull.inf PeCoffExtraActionLib|MdePkg/Library/BasePeCoffExtraActionLibNull/BasePeCoffExtraActionLibNull.inf - CustomizedDisplayLib|MdeModulePkg/Library/CustomizedDisplayLib/CustomizedDisplayLib.inf # # Platform # @@ -193,7 +192,6 @@ } MdeModulePkg/Universal/HiiDatabaseDxe/HiiDatabaseDxe.inf MdeModulePkg/Universal/SetupBrowserDxe/SetupBrowserDxe.inf - MdeModulePkg/Universal/DisplayEngineDxe/DisplayEngineDxe.inf MdeModulePkg/Universal/Console/GraphicsConsoleDxe/GraphicsConsoleDxe.inf MdeModulePkg/Universal/Console/TerminalDxe/TerminalDxe.inf diff --git a/MdeModulePkg/Include/Library/CustomizedDisplayLib.h b/MdeModulePkg/Include/Library/CustomizedDisplayLib.h deleted file mode 100644 index 31e1091e88..0000000000 --- a/MdeModulePkg/Include/Library/CustomizedDisplayLib.h +++ /dev/null @@ -1,356 +0,0 @@ -/** @file - This library class defines a set of interfaces to customize Display module - -Copyright (c) 2013, Intel Corporation. All rights reserved.
-This program and the accompanying materials are licensed and made available under -the terms and conditions of the BSD License that accompanies this distribution. -The full text of the license may be found at -http://opensource.org/licenses/bsd-license.php. - -THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, -WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. - -**/ - -#ifndef __CUSTOMIZED_DISPLAY_LIB_H__ -#define __CUSTOMIZED_DISPLAY_LIB_H__ - -#include - -/** -+------------------------------------------------------------------------------+ -| Setup Page | -+------------------------------------------------------------------------------+ - -Statement -Statement -Statement - - - - - -+------------------------------------------------------------------------------+ -| F9=Reset to Defaults F10=Save | -| ^"=Move Highlight Toggles Checkbox Esc=Exit | -+------------------------------------------------------------------------------+ - StatusBar -**/ - -/** - This funtion defines Page Frame and Backgroud. - - Based on the above layout, it will be responsible for HeaderHeight, FooterHeight, - StatusBarHeight and Backgroud. And, it will reserve Screen for Statement. - - @param[in] FormData Form Data to be shown in Page. - @param[out] ScreenForStatement Screen to be used for Statement. (Prompt, Value and Help) - - @return Status -**/ -EFI_STATUS -EFIAPI -DisplayPageFrame ( - IN FORM_DISPLAY_ENGINE_FORM *FormData, - OUT EFI_SCREEN_DESCRIPTOR *ScreenForStatement - ); - -/** - Clear Screen to the initial state. -**/ -VOID -EFIAPI -ClearDisplayPage ( - VOID - ); - -/** - This function updates customized key panel's help information. - The library will prepare those Strings for the basic key, ESC, Enter, Up/Down/Left/Right, +/-. - and arrange them in Footer panel. - - @param[in] FormData Form Data to be shown in Page. FormData has the highlighted statement. - @param[in] Statement The statement current selected. - @param[in] Selected Whether or not a tag be selected. TRUE means Enter has hit this question. -**/ -VOID -EFIAPI -RefreshKeyHelp ( - IN FORM_DISPLAY_ENGINE_FORM *FormData, - IN FORM_DISPLAY_ENGINE_STATEMENT *Statement, - IN BOOLEAN Selected - ); - -/** - Update status bar. - - This function updates the status bar on the bottom of menu screen. It just shows StatusBar. - Original logic in this function should be splitted out. - - @param[in] MessageType The type of message to be shown. InputError or Configuration Changed. - @param[in] State Show or Clear Message. -**/ -VOID -EFIAPI -UpdateStatusBar ( - IN UINTN MessageType, - IN BOOLEAN State - ); - -/** - Create popup window. - - This function draws OEM/Vendor specific pop up windows. - - @param[out] Key User Input Key - @param ... String to be shown in Popup. The variable argument list is terminated by a NULL. - -**/ -VOID -EFIAPI -CreateDialog ( - OUT EFI_INPUT_KEY *Key, OPTIONAL - ... - ); - -/** - Confirm how to handle the changed data. - - @return Action BROWSER_ACTION_SUBMIT, BROWSER_ACTION_DISCARD or other values. -**/ -UINTN -EFIAPI -ConfirmDataChange ( - VOID - ); - -/** - OEM specifies whether Setup exits Page by ESC key. - - This function customized the behavior that whether Setup exits Page so that - system able to boot when configuration is not changed. - - @retval TRUE Exits FrontPage - @retval FALSE Don't exit FrontPage. -**/ -BOOLEAN -EFIAPI -FormExitPolicy ( - VOID - ); - -/** - Set Timeout value for a ceratain Form to get user response. - - This function allows to set timeout value on a ceratain form if necessary. - If timeout is not zero, the form will exit if user has no response in timeout. - - @param[in] FormData Form Data to be shown in Page - - @return 0 No timeout for this form. - @return > 0 Timeout value in 100 ns units. -**/ -UINT64 -EFIAPI -FormExitTimeout ( - IN FORM_DISPLAY_ENGINE_FORM *FormData - ); - -// -// Print Functions -// -/** - Prints a unicode string to the default console, at - the supplied cursor position, using L"%s" format. - - @param Column The cursor position to print the string at. When it is -1, use current Position. - @param Row The cursor position to print the string at. When it is -1, use current Position. - @param String String pointer. - - @return Length of string printed to the console - -**/ -UINTN -EFIAPI -PrintStringAt ( - IN UINTN Column, - IN UINTN Row, - IN CHAR16 *String - ); - - -/** - Prints a unicode string with the specified width to the default console, at - the supplied cursor position, using L"%s" format. - - @param Column The cursor position to print the string at. When it is -1, use current Position. - @param Row The cursor position to print the string at. When it is -1, use current Position. - @param String String pointer. - @param Width Width for String to be printed. If the print length of String < Width, - Space char (L' ') will be used to append String. - - @return Length of string printed to the console - -**/ -UINTN -EFIAPI -PrintStringAtWithWidth ( - IN UINTN Column, - IN UINTN Row, - IN CHAR16 *String, - IN UINTN Width - ); - -/** - Prints a chracter to the default console, at - the supplied cursor position, using L"%c" format. - - @param Column The cursor position to print the string at. When it is -1, use current Position. - @param Row The cursor position to print the string at. When it is -1, use current Position. - @param Character Character to print. - - @return Length of string printed to the console. - -**/ -UINTN -EFIAPI -PrintCharAt ( - IN UINTN Column, - IN UINTN Row, - CHAR16 Character - ); - -/** - Clear retangle with specified text attribute. - - @param LeftColumn Left column of retangle. - @param RightColumn Right column of retangle. - @param TopRow Start row of retangle. - @param BottomRow End row of retangle. - @param TextAttribute The character foreground and background. - -**/ -VOID -EFIAPI -ClearLines ( - IN UINTN LeftColumn, - IN UINTN RightColumn, - IN UINTN TopRow, - IN UINTN BottomRow, - IN UINTN TextAttribute - ); - -// -// Color Setting Functions -// -/** - Get OEM/Vendor specific popup attribute colors. - - @retval Byte code color setting for popup color. -**/ -UINT8 -EFIAPI -GetPopupColor ( - VOID - ); - -/** - Get OEM/Vendor specific popup attribute colors. - - @retval Byte code color setting for popup inverse color. -**/ -UINT8 -EFIAPI -GetPopupInverseColor ( - VOID - ); - -/** - Get OEM/Vendor specific PickList color attribute. - - @retval Byte code color setting for pick list color. -**/ -UINT8 -EFIAPI -GetPickListColor ( - VOID - ); - -/** - Get OEM/Vendor specific arrow color attribute. - - @retval Byte code color setting for arrow color. -**/ -UINT8 -EFIAPI -GetArrowColor ( - VOID - ); - -/** - Get OEM/Vendor specific info text color attribute. - - @retval Byte code color setting for info text color. -**/ -UINT8 -EFIAPI -GetInfoTextColor ( - VOID - ); - -/** - Get OEM/Vendor specific help text color attribute. - - @retval Byte code color setting for help text color. -**/ -UINT8 -EFIAPI -GetHelpTextColor ( - VOID - ); - -/** - Get OEM/Vendor specific grayed out text color attribute. - - @retval Byte code color setting for grayed out text color. -**/ -UINT8 -EFIAPI -GetGrayedTextColor ( - VOID - ); - -/** - Get OEM/Vendor specific highlighted text color attribute. - - @retval Byte code color setting for highlight text color. -**/ -UINT8 -EFIAPI -GetHighlightTextColor ( - VOID - ); - -/** - Get OEM/Vendor specific field text color attribute. - - @retval Byte code color setting for field text color. -**/ -UINT8 -EFIAPI -GetFieldTextColor ( - VOID - ); - -/** - Get OEM/Vendor specific subtitle text color attribute. - - @retval Byte code color setting for subtitle text color. -**/ -UINT8 -EFIAPI -GetSubTitleTextColor ( - VOID - ); - -#endif diff --git a/MdeModulePkg/Include/Protocol/DisplayProtocol.h b/MdeModulePkg/Include/Protocol/DisplayProtocol.h deleted file mode 100644 index d4f0debf9c..0000000000 --- a/MdeModulePkg/Include/Protocol/DisplayProtocol.h +++ /dev/null @@ -1,350 +0,0 @@ -/** @file - FormDiplay protocol to show Form - -Copyright (c) 2013, Intel Corporation. All rights reserved.
-This program and the accompanying materials are licensed and made available under -the terms and conditions of the BSD License that accompanies this distribution. -The full text of the license may be found at -http://opensource.org/licenses/bsd-license.php. - -THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, -WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. - -**/ - -#ifndef __DISPLAY_PROTOCOL_H__ -#define __DISPLAY_PROTOCOL_H__ - -#include - -#define EDKII_FORM_DISPLAY_ENGINE_PROTOCOL_GUID \ - { 0x9bbe29e9, 0xfda1, 0x41ec, { 0xad, 0x52, 0x45, 0x22, 0x13, 0x74, 0x2d, 0x2e } } - -// -// Do nothing. -// -#define BROWSER_ACTION_NONE BIT16 -// -// ESC Exit -// -#define BROWSER_ACTION_FORM_EXIT BIT17 - -#define BROWSER_SUCCESS 0x0 -#define BROWSER_ERROR BIT31 -#define BROWSER_SUBMIT_FAIL BROWSER_ERROR | 0x01 -#define BROWSER_NO_SUBMIT_IF BROWSER_ERROR | 0x02 -#define BROWSER_FORM_NOT_FOUND BROWSER_ERROR | 0x03 -#define BROWSER_FORM_SUPPRESS BROWSER_ERROR | 0x04 -#define BROWSER_PROTOCOL_NOT_FOUND BROWSER_ERROR | 0x05 - -#define FORM_DISPLAY_ENGINE_STATEMENT_VERSION_1 0x10000 -#define FORM_DISPLAY_ENGINE_VERSION_1 0x10000 - -typedef struct { - // - // HII Data Type - // - UINT8 Type; - // - // Buffer Data and Length if Type is EFI_IFR_TYPE_BUFFER or EFI_IFR_TYPE_STRING - // - UINT8 *Buffer; - UINT16 BufferLen; - EFI_IFR_TYPE_VALUE Value; -} EFI_HII_VALUE; - -#define DISPLAY_QUESTION_OPTION_SIGNATURE SIGNATURE_32 ('Q', 'O', 'P', 'T') - -typedef struct { - UINTN Signature; - LIST_ENTRY Link; - // - // OneOfOption Data - // - EFI_IFR_ONE_OF_OPTION *OptionOpCode; - // - // Option ImageId and AnimationId - // - EFI_IMAGE_ID ImageId; - EFI_ANIMATION_ID AnimationId; -} DISPLAY_QUESTION_OPTION; - -#define DISPLAY_QUESTION_OPTION_FROM_LINK(a) CR (a, DISPLAY_QUESTION_OPTION, Link, DISPLAY_QUESTION_OPTION_SIGNATURE) - -typedef struct _FORM_DISPLAY_ENGINE_STATEMENT FORM_DISPLAY_ENGINE_STATEMENT; -typedef struct _FORM_DISPLAY_ENGINE_FORM FORM_DISPLAY_ENGINE_FORM; - -#define STATEMENT_VALID 0x0 -#define STATEMENT_INVALID BIT31 - -#define INCOSISTENT_IF_TRUE STATEMENT_INVALID | 0x01 -#define WARNING_IF_TRUE STATEMENT_INVALID | 0x02 -#define STRING_TOO_LONG STATEMENT_INVALID | 0x03 -// ... to be extended. - -typedef struct { - // - // StringId for INCONSITENT_IF or WARNING_IF - // - EFI_STRING_ID StringId; - // - // TimeOut for WARNING_IF - // - UINT8 TimeOut; -} STATEMENT_ERROR_INFO; - -/** - Perform value check for a question. - - @param Form Form where Statement is in. - @param Statement Value will check for it. - @param Value New value will be checked. - - @retval Status Value Status - -**/ -typedef -UINT32 -(EFIAPI *VALIDATE_QUESTION) ( - IN FORM_DISPLAY_ENGINE_FORM *Form, - IN FORM_DISPLAY_ENGINE_STATEMENT *Statement, - IN EFI_HII_VALUE *Value, - OUT STATEMENT_ERROR_INFO *ErrorInfo - ); - -/** - Perform Password check. - Passwork may be encrypted by driver that requires the specific check. - - @param Form Form where Password Statement is in. - @param Statement Password statement - @param PasswordString Password string to be checked. It may be NULL. - NULL means to restore password. - "" string can be used to checked whether old password does exist. - - @return Status Status of Password check. -**/ -typedef -EFI_STATUS -(EFIAPI *PASSWORD_CHECK) ( - IN FORM_DISPLAY_ENGINE_FORM *Form, - IN FORM_DISPLAY_ENGINE_STATEMENT *Statement, - IN EFI_STRING PasswordString OPTIONAL - ); - -#define FORM_DISPLAY_ENGINE_STATEMENT_SIGNATURE SIGNATURE_32 ('F', 'S', 'T', 'A') - -// -// Attribute for Statement and Form -// -#define HII_DISPLAY_GRAYOUT BIT0 -#define HII_DISPLAY_LOCK BIT1 -#define HII_DISPLAY_READONLY BIT2 -#define HII_DISPLAY_MODAL BIT3 - -struct _FORM_DISPLAY_ENGINE_STATEMENT{ - UINTN Signature; - // - // Version for future structure extension - // - UINTN Version; - // - // link to all the statement which will show in the display form. - // - LIST_ENTRY DisplayLink; - // - // Pointer to statement opcode. - // for Guided Opcode. All buffers will be here if GUIDED opcode scope is set. - // - EFI_IFR_OP_HEADER *OpCode; - // - // Question CurrentValue - // - EFI_HII_VALUE CurrentValue; - // - // Flag to describe whether setting is changed or not. - // Displayer may depend on it to show it with the different color. - // - BOOLEAN SettingChangedFlag; - // - // nested Statement list inside of EFI_IFR_SUBTITLE - // - LIST_ENTRY NestStatementList; - // - // nested EFI_IFR_ONE_OF_OPTION list (QUESTION_OPTION) - // - LIST_ENTRY OptionListHead; - // - // Statement attributes: GRAYOUT, LOCK and READONLY - // - UINT32 Attribute; - - // - // ValidateQuestion to do InconsistIf check - // It may be NULL if any value is valid. - // - VALIDATE_QUESTION ValidateQuestion; - - // - // Password additional check. It may be NULL when the additional check is not required. - // - PASSWORD_CHECK PasswordCheck; - - // - // Statement ImageId and AnimationId - // - EFI_IMAGE_ID ImageId; - EFI_ANIMATION_ID AnimationId; -}; - -#define FORM_DISPLAY_ENGINE_STATEMENT_FROM_LINK(a) CR (a, FORM_DISPLAY_ENGINE_STATEMENT, DisplayLink, FORM_DISPLAY_ENGINE_STATEMENT_SIGNATURE) - -#define BROWSER_HOT_KEY_SIGNATURE SIGNATURE_32 ('B', 'H', 'K', 'S') - -typedef struct { - UINTN Signature; - LIST_ENTRY Link; - - EFI_INPUT_KEY *KeyData; - // - // Action is Discard, Default, Submit, Reset and Exit. - // - UINT32 Action; - UINT16 DefaultId; - // - // HotKey Help String - // - EFI_STRING HelpString; -} BROWSER_HOT_KEY; - -#define BROWSER_HOT_KEY_FROM_LINK(a) CR (a, BROWSER_HOT_KEY, Link, BROWSER_HOT_KEY_SIGNATURE) - -#define FORM_DISPLAY_ENGINE_FORM_SIGNATURE SIGNATURE_32 ('F', 'F', 'R', 'M') - -struct _FORM_DISPLAY_ENGINE_FORM { - UINTN Signature; - // - // Version for future structure extension - // - UINTN Version; - // - // Statement List inside of Form - // - LIST_ENTRY StatementListHead; - // - // Statement List outside of Form - // - LIST_ENTRY StatementListOSF; - // - // The input screen dimenstions info. - // - EFI_SCREEN_DESCRIPTOR *ScreenDimensions; - // - // FormSet information - // - EFI_GUID FormSetGuid; - // - // HiiHandle can be used to get String, Image or Animation - // - EFI_HII_HANDLE HiiHandle; - - // - // Form ID and Title. - // - UINT16 FormId; - EFI_STRING_ID FormTitle; - // - // Form Attributes: Lock, Modal. - // - UINT32 Attribute; - // - // Flag to describe whether setting is changed or not. - // Displayer depends on it to show ChangedFlag. - // - BOOLEAN SettingChangedFlag; - - // - // Statement to be HighLighted - // - FORM_DISPLAY_ENGINE_STATEMENT *HighLightedStatement; - // - // Event to notify Displayer that FormData is updated to be refreshed. - // - EFI_EVENT FormRefreshEvent; - // - // Additional Hotkey registered by BrowserEx protocol. - // - LIST_ENTRY HotKeyListHead; - - // - // Form ImageId and AnimationId - // - EFI_IMAGE_ID ImageId; - EFI_ANIMATION_ID AnimationId; - - // - // If Status is error, display needs to handle it. - // - UINT32 BrowserStatus; - // - // String for error status. It may be NULL. - // - EFI_STRING ErrorString; -}; - -#define FORM_DISPLAY_ENGINE_FORM_FROM_LINK(a) CR (a, FORM_DISPLAY_ENGINE_FORM, Link, FORM_DISPLAY_ENGINE_FORM_SIGNATURE) - -typedef struct { - FORM_DISPLAY_ENGINE_STATEMENT *SelectedStatement; // Selected Statement and InputValue - - EFI_HII_VALUE InputValue; - - UINT32 Action; // If SelectedStatement is NULL, Action will be used. - // Trig Action (Discard, Default, Submit, Reset and Exit) - UINT16 DefaultId; -} USER_INPUT; - -/** - Display one form, and return user input. - - @param FormData Form Data to be shown. - @param UserInputData User input data. - - @retval EFI_SUCCESS Form Data is shown, and user input is got. -**/ -typedef -EFI_STATUS -(EFIAPI *FORM_DISPLAY) ( - IN FORM_DISPLAY_ENGINE_FORM *FormData, - OUT USER_INPUT *UserInputData -); - -/** - Exit Display and Clear Screen to the original state. - -**/ -typedef -VOID -(EFIAPI *EXIT_DISPLAY) ( - VOID -); - -/** - Confirm how to handle the changed data. - - @return Action of Submit, Discard and None -**/ -typedef -UINTN -(EFIAPI *CONFIRM_DATA_CHANGE) ( - VOID -); - -typedef struct { - FORM_DISPLAY FormDisplay; - EXIT_DISPLAY ExitDisplay; - CONFIRM_DATA_CHANGE ConfirmDataChange; -} EDKII_FORM_DISPLAY_ENGINE_PROTOCOL; - -extern EFI_GUID gEdkiiFormDisplayEngineProtocolGuid; -#endif diff --git a/MdeModulePkg/Include/Protocol/FormBrowserEx2.h b/MdeModulePkg/Include/Protocol/FormBrowserEx2.h deleted file mode 100644 index 105ac0308f..0000000000 --- a/MdeModulePkg/Include/Protocol/FormBrowserEx2.h +++ /dev/null @@ -1,90 +0,0 @@ -/** @file - Extension Form Browser Protocol provides the services that can be used to - register the different hot keys for the standard Browser actions described in UEFI specification. - -Copyright (c) 2013, Intel Corporation. All rights reserved.
-This program and the accompanying materials are licensed and made available under -the terms and conditions of the BSD License that accompanies this distribution. -The full text of the license may be found at -http://opensource.org/licenses/bsd-license.php. - -THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, -WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. - -**/ - -#ifndef __FORM_BROWSER_EXTENSION2_H__ -#define __FORM_BROWSER_EXTENSION2_H__ - -#include - -#define EDKII_FORM_BROWSER_EXTENSION2_PROTOCOL_GUID \ - { 0xa770c357, 0xb693, 0x4e6d, { 0xa6, 0xcf, 0xd2, 0x1c, 0x72, 0x8e, 0x55, 0xb }} - -typedef struct _EDKII_FORM_BROWSER_EXTENSION2_PROTOCOL EDKII_FORM_BROWSER_EXTENSION2_PROTOCOL; - -#define BROWSER_EXTENSION2_VERSION_1 0x10000 - -/** - Check whether the browser data has been modified. - - @retval TRUE Browser data is modified. - @retval FALSE No browser data is modified. - -**/ -typedef -BOOLEAN -(EFIAPI *IS_BROWSER_DATA_MODIFIED) ( - VOID - ); - -/** - Execute the action requested by the Action parameter. - - @param[in] Action Execute the request action. - @param[in] DefaultId The default Id info when need to load default value. - - @retval EFI_SUCCESS Execute the request action succss. - -**/ -typedef -EFI_STATUS -(EFIAPI *EXECUTE_ACTION) ( - IN UINT32 Action, - IN UINT16 DefaultId - ); - -#define FORM_ENTRY_INFO_SIGNATURE SIGNATURE_32 ('f', 'e', 'i', 's') - -typedef struct { - UINTN Signature; - LIST_ENTRY Link; - - EFI_HII_HANDLE HiiHandle; - EFI_GUID FormSetGuid; - EFI_FORM_ID FormId; - EFI_QUESTION_ID QuestionId; -} FORM_ENTRY_INFO; - -#define FORM_ENTRY_INFO_FROM_LINK(a) CR (a, FORM_ENTRY_INFO, Link, FORM_ENTRY_INFO_SIGNATURE) - -struct _EDKII_FORM_BROWSER_EXTENSION2_PROTOCOL { - /// - /// Version for protocol future extension. - /// - UINT32 Version; - SET_SCOPE SetScope; - REGISTER_HOT_KEY RegisterHotKey; - REGISTER_EXIT_HANDLER RegiserExitHandler; - IS_BROWSER_DATA_MODIFIED IsBrowserDataModified; - EXECUTE_ACTION ExecuteAction; - /// - /// A list of type FORMID_INFO is Browser View Form History List. - /// - LIST_ENTRY FormViewHistoryHead; -}; - -extern EFI_GUID gEdkiiFormBrowserEx2ProtocolGuid; - -#endif - diff --git a/MdeModulePkg/Library/CustomizedDisplayLib/Colors.h b/MdeModulePkg/Library/CustomizedDisplayLib/Colors.h deleted file mode 100644 index 2db8b99614..0000000000 --- a/MdeModulePkg/Library/CustomizedDisplayLib/Colors.h +++ /dev/null @@ -1,44 +0,0 @@ -/** @file -MACRO definitions for color used in Setup Browser. - -Copyright (c) 2004 - 2011, Intel Corporation. All rights reserved.
-This program and the accompanying materials -are licensed and made available under the terms and conditions of the BSD License -which accompanies this distribution. The full text of the license may be found at -http://opensource.org/licenses/bsd-license.php - -THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, -WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. - -**/ -// -// Unicode collation protocol in - -#ifndef _COLORS_H_ -#define _COLORS_H_ - -// -// Screen Color Settings -// -#define PICKLIST_HIGHLIGHT_TEXT EFI_WHITE -#define PICKLIST_HIGHLIGHT_BACKGROUND EFI_BACKGROUND_CYAN -#define TITLE_TEXT EFI_WHITE -#define TITLE_BACKGROUND EFI_BACKGROUND_BLUE -#define KEYHELP_TEXT EFI_LIGHTGRAY -#define KEYHELP_BACKGROUND EFI_BACKGROUND_BLACK -#define SUBTITLE_BACKGROUND EFI_BACKGROUND_LIGHTGRAY -#define BANNER_TEXT EFI_BLUE -#define BANNER_BACKGROUND EFI_BACKGROUND_LIGHTGRAY -#define FIELD_TEXT_GRAYED EFI_DARKGRAY -#define FIELD_BACKGROUND EFI_BACKGROUND_LIGHTGRAY -#define POPUP_TEXT EFI_LIGHTGRAY -#define POPUP_BACKGROUND EFI_BACKGROUND_BLUE -#define POPUP_INVERSE_TEXT EFI_LIGHTGRAY -#define POPUP_INVERSE_BACKGROUND EFI_BACKGROUND_BLACK -#define HELP_TEXT EFI_BLUE -#define ERROR_TEXT EFI_RED | EFI_BRIGHT -#define INFO_TEXT EFI_YELLOW | EFI_BRIGHT -#define ARROW_TEXT EFI_RED | EFI_BRIGHT -#define ARROW_BACKGROUND EFI_BACKGROUND_LIGHTGRAY - -#endif diff --git a/MdeModulePkg/Library/CustomizedDisplayLib/CustomizedDisplayLib.c b/MdeModulePkg/Library/CustomizedDisplayLib/CustomizedDisplayLib.c deleted file mode 100644 index aa28146b02..0000000000 --- a/MdeModulePkg/Library/CustomizedDisplayLib/CustomizedDisplayLib.c +++ /dev/null @@ -1,921 +0,0 @@ -/** @file - - This library class defines a set of interfaces to customize Display module - -Copyright (c) 2013, Intel Corporation. All rights reserved.
-This program and the accompanying materials are licensed and made available under -the terms and conditions of the BSD License that accompanies this distribution. -The full text of the license may be found at -http://opensource.org/licenses/bsd-license.php. - -THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, -WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. - -**/ -#include "CustomizedDisplayLibInternal.h" - -EFI_GUID gCustomizedDisplayLibGuid = { 0x99fdc8fd, 0x849b, 0x4eba, { 0xad, 0x13, 0xfb, 0x96, 0x99, 0xc9, 0xa, 0x4d } }; - -EFI_HII_HANDLE mCDLStringPackHandle; -UINT16 gClassOfVfr; // Formset class information -BOOLEAN gLibIsFirstForm = TRUE; -BANNER_DATA *gBannerData; - -UINTN gFooterHeight; - -/** -+------------------------------------------------------------------------------+ -| Setup Page | -+------------------------------------------------------------------------------+ - -Statement -Statement -Statement - - - - - -+------------------------------------------------------------------------------+ -| F9=Reset to Defaults F10=Save | -| ^"=Move Highlight Toggles Checkbox Esc=Exit | -+------------------------------------------------------------------------------+ - StatusBar -**/ - -/** - This funtion defines Page Frame and Backgroud. - - Based on the above layout, it will be responsible for HeaderHeight, FooterHeight, - StatusBarHeight and Backgroud. And, it will reserve Screen for Statement. - - @param[in] FormData Form Data to be shown in Page. - @param[out] ScreenForStatement Screen to be used for Statement. (Prompt, Value and Help) - - @return Status -**/ -EFI_STATUS -EFIAPI -DisplayPageFrame ( - IN FORM_DISPLAY_ENGINE_FORM *FormData, - OUT EFI_SCREEN_DESCRIPTOR *ScreenForStatement - ) -{ - EFI_STATUS Status; - - ASSERT (FormData != NULL && ScreenForStatement != NULL); - if (FormData == NULL || ScreenForStatement == NULL) { - return EFI_INVALID_PARAMETER; - } - - Status = ScreenDiemensionInfoValidate (FormData); - if (EFI_ERROR (Status)) { - return Status; - } - - gClassOfVfr = FORMSET_CLASS_PLATFORM_SETUP; - - ProcessExternedOpcode(FormData); - - // - // Calculate the ScreenForStatement. - // - ScreenForStatement->BottomRow = gScreenDimensions.BottomRow - STATUS_BAR_HEIGHT - gFooterHeight; - if (gClassOfVfr == FORMSET_CLASS_FRONT_PAGE) { - ScreenForStatement->TopRow = gScreenDimensions.TopRow + FRONT_PAGE_HEADER_HEIGHT; - } else { - ScreenForStatement->TopRow = gScreenDimensions.TopRow + NONE_FRONT_PAGE_HEADER_HEIGHT; - } - ScreenForStatement->LeftColumn = gScreenDimensions.LeftColumn; - ScreenForStatement->RightColumn = gScreenDimensions.RightColumn; - - if ((gLibIsFirstForm) || ((FormData->Attribute & HII_DISPLAY_MODAL) != 0)) { - // - // Ensure we are in Text mode - // - gST->ConOut->SetAttribute (gST->ConOut, EFI_TEXT_ATTR (EFI_LIGHTGRAY, EFI_BLACK)); - ClearLines (0, gScreenDimensions.RightColumn, 0, gScreenDimensions.BottomRow, KEYHELP_BACKGROUND); - gLibIsFirstForm = FALSE; - } - - // - // Don't print frame for modal form. - // - if ((FormData->Attribute & HII_DISPLAY_MODAL) != 0) { - return EFI_SUCCESS; - } - - if (gClassOfVfr == FORMSET_CLASS_FRONT_PAGE) { - PrintBannerInfo (FormData); - } - - PrintFramework (FormData); - - UpdateStatusBar(NV_UPDATE_REQUIRED, FormData->SettingChangedFlag); - - return EFI_SUCCESS; -} - -/** - This function updates customized key panel's help information. - The library will prepare those Strings for the basic key, ESC, Enter, Up/Down/Left/Right, +/-. - and arrange them in Footer panel. - - @param[in] FormData Form Data to be shown in Page. FormData has the highlighted statement. - @param[in] Statement The statement current selected. - @param[in] Selected Whether or not a tag be selected. TRUE means Enter has hit this question. -**/ -VOID -EFIAPI -RefreshKeyHelp ( - IN FORM_DISPLAY_ENGINE_FORM *FormData, - IN FORM_DISPLAY_ENGINE_STATEMENT *Statement, - IN BOOLEAN Selected - ) -{ - UINTN SecCol; - UINTN ThdCol; - UINTN LeftColumnOfHelp; - UINTN RightColumnOfHelp; - UINTN TopRowOfHelp; - UINTN BottomRowOfHelp; - UINTN StartColumnOfHelp; - EFI_IFR_NUMERIC *NumericOp; - EFI_IFR_DATE *DateOp; - EFI_IFR_TIME *TimeOp; - BOOLEAN HexDisplay; - - ASSERT (FormData != NULL); - if (FormData == NULL) { - return; - } - - gST->ConOut->SetAttribute (gST->ConOut, KEYHELP_TEXT | KEYHELP_BACKGROUND); - - if ((FormData->Attribute & HII_DISPLAY_MODAL) != 0) { - return; - } - - SecCol = gScreenDimensions.LeftColumn + (gScreenDimensions.RightColumn - gScreenDimensions.LeftColumn) / 3; - ThdCol = gScreenDimensions.LeftColumn + (gScreenDimensions.RightColumn - gScreenDimensions.LeftColumn) / 3 * 2; - - StartColumnOfHelp = gScreenDimensions.LeftColumn + 2; - LeftColumnOfHelp = gScreenDimensions.LeftColumn + 1; - RightColumnOfHelp = gScreenDimensions.RightColumn - 2; - TopRowOfHelp = gScreenDimensions.BottomRow - STATUS_BAR_HEIGHT - gFooterHeight + 1; - BottomRowOfHelp = gScreenDimensions.BottomRow - STATUS_BAR_HEIGHT - 2; - - ClearLines (LeftColumnOfHelp, RightColumnOfHelp, TopRowOfHelp, BottomRowOfHelp, KEYHELP_TEXT | KEYHELP_BACKGROUND); - if (Statement == NULL) { - // - // Print Key for Form without showable statement. - // - PrintHotKeyHelpString (FormData); - PrintStringAt (ThdCol, BottomRowOfHelp, gEscapeString); - return; - } - - HexDisplay = FALSE; - NumericOp = NULL; - DateOp = NULL; - TimeOp = NULL; - if (Statement->OpCode->OpCode == EFI_IFR_NUMERIC_OP) { - NumericOp = (EFI_IFR_NUMERIC *) Statement->OpCode; - HexDisplay = (NumericOp->Flags & EFI_IFR_DISPLAY_UINT_HEX) == EFI_IFR_DISPLAY_UINT_HEX; - } else if (Statement->OpCode->OpCode == EFI_IFR_DATE_OP) { - DateOp = (EFI_IFR_DATE *) Statement->OpCode; - HexDisplay = (DateOp->Flags & EFI_IFR_DISPLAY_UINT_HEX) == EFI_IFR_DISPLAY_UINT_HEX; - } else if (Statement->OpCode->OpCode == EFI_IFR_TIME_OP) { - TimeOp = (EFI_IFR_TIME *) Statement->OpCode; - HexDisplay = (TimeOp->Flags & EFI_IFR_DISPLAY_UINT_HEX) == EFI_IFR_DISPLAY_UINT_HEX; - } - switch (Statement->OpCode->OpCode) { - case EFI_IFR_ORDERED_LIST_OP: - case EFI_IFR_ONE_OF_OP: - case EFI_IFR_NUMERIC_OP: - case EFI_IFR_TIME_OP: - case EFI_IFR_DATE_OP: - if (!Selected) { - PrintHotKeyHelpString (FormData); - - if (gClassOfVfr == FORMSET_CLASS_PLATFORM_SETUP) { - PrintStringAt (ThdCol, BottomRowOfHelp, gEscapeString); - } - - if ((Statement->OpCode->OpCode == EFI_IFR_DATE_OP) || - (Statement->OpCode->OpCode == EFI_IFR_TIME_OP)) { - PrintAt ( - 0, - StartColumnOfHelp, - BottomRowOfHelp, - L"%c%c%c%c%s", - ARROW_UP, - ARROW_DOWN, - ARROW_RIGHT, - ARROW_LEFT, - gMoveHighlight - ); - PrintStringAt (SecCol, BottomRowOfHelp, gEnterString); - PrintStringAt (StartColumnOfHelp, TopRowOfHelp, gAdjustNumber); - } else { - PrintAt (0, StartColumnOfHelp, BottomRowOfHelp, L"%c%c%s", ARROW_UP, ARROW_DOWN, gMoveHighlight); - if (Statement->OpCode->OpCode == EFI_IFR_NUMERIC_OP && NumericOp != NULL && LibGetFieldFromNum(Statement->OpCode) != 0) { - PrintStringAt (StartColumnOfHelp, TopRowOfHelp, gAdjustNumber); - } - PrintStringAt (SecCol, BottomRowOfHelp, gEnterString); - } - } else { - PrintStringAt (SecCol, BottomRowOfHelp, gEnterCommitString); - - // - // If it is a selected numeric with manual input, display different message - // - if ((Statement->OpCode->OpCode == EFI_IFR_NUMERIC_OP) || - (Statement->OpCode->OpCode == EFI_IFR_DATE_OP) || - (Statement->OpCode->OpCode == EFI_IFR_TIME_OP)) { - PrintStringAt ( - SecCol, - TopRowOfHelp, - HexDisplay ? gHexNumericInput : gDecNumericInput - ); - } else if (Statement->OpCode->OpCode != EFI_IFR_ORDERED_LIST_OP) { - PrintAt (0, StartColumnOfHelp, BottomRowOfHelp, L"%c%c%s", ARROW_UP, ARROW_DOWN, gMoveHighlight); - } - - if (Statement->OpCode->OpCode == EFI_IFR_ORDERED_LIST_OP) { - PrintStringAt (StartColumnOfHelp, TopRowOfHelp, gPlusString); - PrintStringAt (ThdCol, TopRowOfHelp, gMinusString); - } - - PrintStringAt (ThdCol, BottomRowOfHelp, gEnterEscapeString); - } - break; - - case EFI_IFR_CHECKBOX_OP: - PrintHotKeyHelpString (FormData); - - if (gClassOfVfr == FORMSET_CLASS_PLATFORM_SETUP) { - PrintStringAt (ThdCol, BottomRowOfHelp, gEscapeString); - } - - PrintAt (0, StartColumnOfHelp, BottomRowOfHelp, L"%c%c%s", ARROW_UP, ARROW_DOWN, gMoveHighlight); - PrintStringAt (SecCol, BottomRowOfHelp, gToggleCheckBox); - break; - - case EFI_IFR_REF_OP: - case EFI_IFR_PASSWORD_OP: - case EFI_IFR_STRING_OP: - case EFI_IFR_TEXT_OP: - case EFI_IFR_ACTION_OP: - case EFI_IFR_RESET_BUTTON_OP: - case EFI_IFR_SUBTITLE_OP: - if (!Selected) { - PrintHotKeyHelpString (FormData); - - if (gClassOfVfr == FORMSET_CLASS_PLATFORM_SETUP) { - PrintStringAt (ThdCol, BottomRowOfHelp, gEscapeString); - } - - PrintAt (0, StartColumnOfHelp, BottomRowOfHelp, L"%c%c%s", ARROW_UP, ARROW_DOWN, gMoveHighlight); - if (Statement->OpCode->OpCode != EFI_IFR_TEXT_OP && Statement->OpCode->OpCode != EFI_IFR_SUBTITLE_OP) { - PrintStringAt (SecCol, BottomRowOfHelp, gEnterString); - } - } else { - if (Statement->OpCode->OpCode != EFI_IFR_REF_OP) { - PrintStringAt ( - (gScreenDimensions.RightColumn - LibGetStringWidth (gEnterCommitString) / 2) / 2, - BottomRowOfHelp, - gEnterCommitString - ); - PrintStringAt (ThdCol, BottomRowOfHelp, gEnterEscapeString); - } - } - break; - - default: - break; - } -} - -/** - Update status bar. - - This function updates the status bar on the bottom of menu screen. It just shows StatusBar. - Original logic in this function should be splitted out. - - @param[in] MessageType The type of message to be shown. InputError or Configuration Changed. - @param[in] State Show or Clear Message. -**/ -VOID -EFIAPI -UpdateStatusBar ( - IN UINTN MessageType, - IN BOOLEAN State - ) -{ - UINTN Index; - CHAR16 OptionWidth; - - OptionWidth = (CHAR16) ((gScreenDimensions.RightColumn - gScreenDimensions.LeftColumn) / 3); - - switch (MessageType) { - case INPUT_ERROR: - if (State) { - gST->ConOut->SetAttribute (gST->ConOut, ERROR_TEXT); - PrintStringAt ( - gScreenDimensions.LeftColumn + OptionWidth, - gScreenDimensions.BottomRow - 1, - gInputErrorMessage - ); - } else { - gST->ConOut->SetAttribute (gST->ConOut, KEYHELP_BACKGROUND); - for (Index = 0; Index < (LibGetStringWidth (gInputErrorMessage) - 2) / 2; Index++) { - PrintStringAt (gScreenDimensions.LeftColumn + OptionWidth + Index, gScreenDimensions.BottomRow - 1, L" "); - } - } - break; - - case NV_UPDATE_REQUIRED: - // - // Global setting support. Show configuration change on every form. - // - if (State) { - gST->ConOut->SetAttribute (gST->ConOut, INFO_TEXT); - PrintStringAt ( - gScreenDimensions.LeftColumn + OptionWidth * 2, - gScreenDimensions.BottomRow - 1, - gNvUpdateMessage - ); - } else { - gST->ConOut->SetAttribute (gST->ConOut, KEYHELP_BACKGROUND); - for (Index = 0; Index < (LibGetStringWidth (gNvUpdateMessage) - 2) / 2; Index++) { - PrintStringAt ( - (gScreenDimensions.LeftColumn + OptionWidth * 2 + Index), - gScreenDimensions.BottomRow - 1, - L" " - ); - } - } - break; - - default: - break; - } -} - -/** - Create popup window. It will replace CreateDialog(). - - This function draws OEM/Vendor specific pop up windows. - - @param[out] Key User Input Key - @param ... String to be shown in Popup. The variable argument list is terminated by a NULL. - -**/ -VOID -EFIAPI -CreateDialog ( - OUT EFI_INPUT_KEY *Key, OPTIONAL - ... - ) -{ - VA_LIST Marker; - EFI_INPUT_KEY KeyValue; - EFI_STATUS Status; - UINTN LargestString; - UINTN LineNum; - UINTN Index; - UINTN Count; - CHAR16 Character; - UINTN Start; - UINTN End; - UINTN Top; - UINTN Bottom; - CHAR16 *String; - UINTN DimensionsWidth; - UINTN DimensionsHeight; - UINTN CurrentAttribute; - - // - // If screen dimension info is not ready, get it from console. - // - if (gScreenDimensions.RightColumn == 0 || gScreenDimensions.BottomRow == 0) { - ZeroMem (&gScreenDimensions, sizeof (EFI_SCREEN_DESCRIPTOR)); - gST->ConOut->QueryMode ( - gST->ConOut, - gST->ConOut->Mode->Mode, - &gScreenDimensions.RightColumn, - &gScreenDimensions.BottomRow - ); - } - - DimensionsWidth = gScreenDimensions.RightColumn - gScreenDimensions.LeftColumn; - DimensionsHeight = gScreenDimensions.BottomRow - gScreenDimensions.TopRow; - - LargestString = 0; - LineNum = 0; - VA_START (Marker, Key); - while ((String = VA_ARG (Marker, CHAR16 *)) != NULL) { - LineNum ++; - - if ((LibGetStringWidth (String) / 2) > LargestString) { - LargestString = (LibGetStringWidth (String) / 2); - } - } - VA_END (Marker); - - if ((LargestString + 2) > DimensionsWidth) { - LargestString = DimensionsWidth - 2; - } - - CurrentAttribute = gST->ConOut->Mode->Attribute; - gST->ConOut->EnableCursor (gST->ConOut, FALSE); - gST->ConOut->SetAttribute (gST->ConOut, GetPopupColor ()); - - // - // Subtract the PopUp width from total Columns, allow for one space extra on - // each end plus a border. - // - Start = (DimensionsWidth - LargestString - 2) / 2 + gScreenDimensions.LeftColumn + 1; - End = Start + LargestString + 1; - - Top = ((DimensionsHeight - LineNum - 2) / 2) + gScreenDimensions.TopRow - 1; - Bottom = Top + LineNum + 2; - - Character = BOXDRAW_DOWN_RIGHT; - PrintCharAt (Start, Top, Character); - Character = BOXDRAW_HORIZONTAL; - for (Index = Start; Index + 2 < End; Index++) { - PrintCharAt ((UINTN)-1, (UINTN)-1, Character); - } - - Character = BOXDRAW_DOWN_LEFT; - PrintCharAt ((UINTN)-1, (UINTN)-1, Character); - Character = BOXDRAW_VERTICAL; - - Count = 0; - VA_START (Marker, Key); - for (Index = Top; Index + 2 < Bottom; Index++, Count++) { - String = VA_ARG (Marker, CHAR16*); - - if (String[0] == CHAR_NULL) { - // - // Passing in a NULL results in a blank space - // - ClearLines (Start, End, Index + 1, Index + 1, GetPopupColor ()); - } else if (String[0] == L' ') { - // - // Passing in a space results in the assumption that this is where typing will occur - // - ClearLines (Start + 1, End - 1, Index + 1, Index + 1, POPUP_INVERSE_TEXT | POPUP_INVERSE_BACKGROUND); - PrintStringAt ( - ((DimensionsWidth - LibGetStringWidth (String) / 2) / 2) + gScreenDimensions.LeftColumn + 1, - Index + 1, - String + 1 - ); - } else { - // - // This will clear the background of the line - we never know who might have been - // here before us. This differs from the next clear in that it used the non-reverse - // video for normal printing. - // - ClearLines (Start, End, Index + 1, Index + 1, GetPopupColor ()); - PrintStringAt ( - ((DimensionsWidth - LibGetStringWidth (String) / 2) / 2) + gScreenDimensions.LeftColumn + 1, - Index + 1, - String - ); - } - - gST->ConOut->SetAttribute (gST->ConOut, GetPopupColor ()); - PrintCharAt (Start, Index + 1, Character); - PrintCharAt (End - 1, Index + 1, Character); - } - VA_END (Marker); - - Character = BOXDRAW_UP_RIGHT; - PrintCharAt (Start, Bottom - 1, Character); - Character = BOXDRAW_HORIZONTAL; - for (Index = Start; Index + 2 < End; Index++) { - PrintCharAt ((UINTN)-1, (UINTN) -1, Character); - } - - Character = BOXDRAW_UP_LEFT; - PrintCharAt ((UINTN)-1, (UINTN) -1, Character); - - if (Key != NULL) { - Status = WaitForKeyStroke (&KeyValue); - ASSERT_EFI_ERROR (Status); - CopyMem (Key, &KeyValue, sizeof (EFI_INPUT_KEY)); - } - - gST->ConOut->SetAttribute (gST->ConOut, CurrentAttribute); - gST->ConOut->EnableCursor (gST->ConOut, TRUE); -} - -/** - Confirm how to handle the changed data. - - @return Action BROWSER_ACTION_SUBMIT, BROWSER_ACTION_DISCARD or other values. -**/ -UINTN -EFIAPI -ConfirmDataChange ( - VOID - ) -{ - CHAR16 YesResponse; - CHAR16 NoResponse; - EFI_INPUT_KEY Key; - - gST->ConIn->ReadKeyStroke (gST->ConIn, &Key); - - YesResponse = gYesResponse[0]; - NoResponse = gNoResponse[0]; - - // - // If NV flag is up, prompt user - // - do { - CreateDialog (&Key, gLibEmptyString, gSaveChanges, gAreYouSure, gLibEmptyString, NULL); - } while - ( - (Key.ScanCode != SCAN_ESC) && - ((Key.UnicodeChar | UPPER_LOWER_CASE_OFFSET) != (NoResponse | UPPER_LOWER_CASE_OFFSET)) && - ((Key.UnicodeChar | UPPER_LOWER_CASE_OFFSET) != (YesResponse | UPPER_LOWER_CASE_OFFSET)) - ); - - if (Key.ScanCode == SCAN_ESC) { - return BROWSER_ACTION_NONE; - } else if ((Key.UnicodeChar | UPPER_LOWER_CASE_OFFSET) == (YesResponse | UPPER_LOWER_CASE_OFFSET)) { - return BROWSER_ACTION_SUBMIT; - } else { - return BROWSER_ACTION_DISCARD; - } -} - -/** - OEM specifies whether Setup exits Page by ESC key. - - This function customized the behavior that whether Setup exits Page so that - system able to boot when configuration is not changed. - - @retval TRUE Exits FrontPage - @retval FALSE Don't exit FrontPage. -**/ -BOOLEAN -EFIAPI -FormExitPolicy ( - VOID - ) -{ - return gClassOfVfr == FORMSET_CLASS_FRONT_PAGE ? FALSE : TRUE; -} - -/** - Set Timeout value for a ceratain Form to get user response. - - This function allows to set timeout value on a ceratain form if necessary. - If timeout is not zero, the form will exit if user has no response in timeout. - - @param[in] FormData Form Data to be shown in Page - - @return 0 No timeout for this form. - @return > 0 Timeout value in 100 ns units. -**/ -UINT64 -EFIAPI -FormExitTimeout ( - IN FORM_DISPLAY_ENGINE_FORM *FormData - ) -{ - return 0; -} -// -// Print Functions -// -/** - Prints a unicode string to the default console, at - the supplied cursor position, using L"%s" format. - - @param Column The cursor position to print the string at. When it is -1, use current Position. - @param Row The cursor position to print the string at. When it is -1, use current Position. - @param String String pointer. - - @return Length of string printed to the console - -**/ -UINTN -EFIAPI -PrintStringAt ( - IN UINTN Column, - IN UINTN Row, - IN CHAR16 *String - ) -{ - return PrintAt (0, Column, Row, L"%s", String); -} - -/** - Prints a unicode string to the default console, at - the supplied cursor position, using L"%s" format. - - @param Column The cursor position to print the string at. When it is -1, use current Position. - @param Row The cursor position to print the string at. When it is -1, use current Position. - @param String String pointer. - @param Width Width for String. - - @return Length of string printed to the console - -**/ -UINTN -EFIAPI -PrintStringAtWithWidth ( - IN UINTN Column, - IN UINTN Row, - IN CHAR16 *String, - IN UINTN Width - ) -{ - return PrintAt (Width, Column, Row, L"%s", String); -} - -/** - Prints a chracter to the default console, at - the supplied cursor position, using L"%c" format. - - @param Column The cursor position to print the string at. When it is -1, use current Position. - @param Row The cursor position to print the string at. When it is -1, use current Position. - @param Character Character to print. - - @return Length of string printed to the console. - -**/ -UINTN -EFIAPI -PrintCharAt ( - IN UINTN Column, - IN UINTN Row, - CHAR16 Character - ) -{ - return PrintAt (0, Column, Row, L"%c", Character); -} - -/** - Clear retangle with specified text attribute. - - @param LeftColumn Left column of retangle. - @param RightColumn Right column of retangle. - @param TopRow Start row of retangle. - @param BottomRow End row of retangle. - @param TextAttribute The character foreground and background. - -**/ -VOID -EFIAPI -ClearLines ( - IN UINTN LeftColumn, - IN UINTN RightColumn, - IN UINTN TopRow, - IN UINTN BottomRow, - IN UINTN TextAttribute - ) -{ - CHAR16 *Buffer; - UINTN Row; - - // - // For now, allocate an arbitrarily long buffer - // - Buffer = AllocateZeroPool (0x10000); - ASSERT (Buffer != NULL); - - // - // Set foreground and background as defined - // - gST->ConOut->SetAttribute (gST->ConOut, TextAttribute); - - // - // Much faster to buffer the long string instead of print it a character at a time - // - LibSetUnicodeMem (Buffer, RightColumn - LeftColumn, L' '); - - // - // Clear the desired area with the appropriate foreground/background - // - for (Row = TopRow; Row <= BottomRow; Row++) { - PrintStringAt (LeftColumn, Row, Buffer); - } - - gST->ConOut->SetCursorPosition (gST->ConOut, LeftColumn, TopRow); - - FreePool (Buffer); -} - -// -// Color Setting Functions -// - -/** - Get OEM/Vendor specific popup attribute colors. - - @retval Byte code color setting for popup color. -**/ -UINT8 -EFIAPI -GetPopupColor ( - VOID - ) -{ - return POPUP_TEXT | POPUP_BACKGROUND; -} - -/** - Get OEM/Vendor specific popup attribute colors. - - @retval Byte code color setting for popup inverse color. -**/ -UINT8 -EFIAPI -GetPopupInverseColor ( - VOID - ) -{ - return POPUP_INVERSE_TEXT | POPUP_INVERSE_BACKGROUND; -} - -/** - Get OEM/Vendor specific PickList color attribute. - - @retval Byte code color setting for pick list color. -**/ -UINT8 -EFIAPI -GetPickListColor ( - VOID - ) -{ - return PICKLIST_HIGHLIGHT_TEXT | PICKLIST_HIGHLIGHT_BACKGROUND; -} - -/** - Get OEM/Vendor specific arrow color attribute. - - @retval Byte code color setting for arrow color. -**/ -UINT8 -EFIAPI -GetArrowColor ( - VOID - ) -{ - return ARROW_TEXT | ARROW_BACKGROUND; -} - -/** - Get OEM/Vendor specific info text color attribute. - - @retval Byte code color setting for info text color. -**/ -UINT8 -EFIAPI -GetInfoTextColor ( - VOID - ) -{ - return INFO_TEXT | FIELD_BACKGROUND; -} - -/** - Get OEM/Vendor specific help text color attribute. - - @retval Byte code color setting for help text color. -**/ -UINT8 -EFIAPI -GetHelpTextColor ( - VOID - ) -{ - return HELP_TEXT | FIELD_BACKGROUND; -} - -/** - Get OEM/Vendor specific grayed out text color attribute. - - @retval Byte code color setting for grayed out text color. -**/ -UINT8 -EFIAPI -GetGrayedTextColor ( - VOID - ) -{ - return FIELD_TEXT_GRAYED | FIELD_BACKGROUND; -} - -/** - Get OEM/Vendor specific highlighted text color attribute. - - @retval Byte code color setting for highlight text color. -**/ -UINT8 -EFIAPI -GetHighlightTextColor ( - VOID - ) -{ - return PcdGet8 (PcdBrowserFieldTextHighlightColor) | PcdGet8 (PcdBrowserFieldBackgroundHighlightColor); -} - -/** - Get OEM/Vendor specific field text color attribute. - - @retval Byte code color setting for field text color. -**/ -UINT8 -EFIAPI -GetFieldTextColor ( - VOID - ) -{ - return PcdGet8 (PcdBrowserFieldTextColor) | FIELD_BACKGROUND; -} - -/** - Get OEM/Vendor specific subtitle text color attribute. - - @retval Byte code color setting for subtitle text color. -**/ -UINT8 -EFIAPI -GetSubTitleTextColor ( - VOID - ) -{ - return PcdGet8 (PcdBrowserSubtitleTextColor) | FIELD_BACKGROUND; -} - -/** - Clear Screen to the initial state. -**/ -VOID -EFIAPI -ClearDisplayPage ( - VOID - ) -{ - gST->ConOut->SetAttribute (gST->ConOut, EFI_TEXT_ATTR (EFI_LIGHTGRAY, EFI_BLACK)); - gST->ConOut->ClearScreen (gST->ConOut); - gLibIsFirstForm = TRUE; -} - -/** - Constructor of Customized Display Library Instance. - - @param ImageHandle The firmware allocated handle for the EFI image. - @param SystemTable A pointer to the EFI System Table. - - @retval EFI_SUCCESS The constructor always returns EFI_SUCCESS. - -**/ -EFI_STATUS -EFIAPI -CustomizedDisplayLibConstructor ( - IN EFI_HANDLE ImageHandle, - IN EFI_SYSTEM_TABLE *SystemTable - ) -{ - mCDLStringPackHandle = HiiAddPackages (&gCustomizedDisplayLibGuid, ImageHandle, CustomizedDisplayLibStrings, NULL); - ASSERT (mCDLStringPackHandle != NULL); - - InitializeLibStrings(); - - return EFI_SUCCESS; -} - -/** - Destructor of Customized Display Library Instance. - - @param ImageHandle The firmware allocated handle for the EFI image. - @param SystemTable A pointer to the EFI System Table. - - @retval EFI_SUCCESS The destructor completed successfully. - @retval Other value The destructor did not complete successfully. - -**/ -EFI_STATUS -EFIAPI -CustomizedDisplayLibDestructor ( - IN EFI_HANDLE ImageHandle, - IN EFI_SYSTEM_TABLE *SystemTable - ) -{ - HiiRemovePackages(mCDLStringPackHandle); - - FreeLibStrings (); - - return EFI_SUCCESS; -} - diff --git a/MdeModulePkg/Library/CustomizedDisplayLib/CustomizedDisplayLib.inf b/MdeModulePkg/Library/CustomizedDisplayLib/CustomizedDisplayLib.inf deleted file mode 100644 index ade45b6a51..0000000000 --- a/MdeModulePkg/Library/CustomizedDisplayLib/CustomizedDisplayLib.inf +++ /dev/null @@ -1,74 +0,0 @@ -## -# This file contains an 'Intel Peripheral Driver' and is -# licensed for Intel CPUs and chipsets under the terms of your -# license agreement with Intel or your vendor. This file may -# be modified by the user, subject to additional terms of the -# license agreement -## -## @file -# -# General BDS defines and produce general interfaces for platform BDS driver including: -# 1) BDS boot policy interface; -# 2) BDS boot device connect interface; -# 3) BDS Misc interfaces for mainting boot variable, ouput string, etc. -# -# Copyright (c) 2007 - 2010, Intel Corporation. All rights reserved.
-# This software and associated documentation (if any) is furnished -# under a license and may only be used or copied in accordance -# with the terms of the license. Except as permitted by such -# license, no part of this software or documentation may be -# reproduced, stored in a retrieval system, or transmitted in any -# form or by any means without the express written consent of -# Intel Corporation. -# -## - -[Defines] - INF_VERSION = 0x00010005 - BASE_NAME = CustomizedDisplayLib - FILE_GUID = 80B92017-EC64-4923-938D-94FAEE85832E - MODULE_TYPE = DXE_DRIVER - VERSION_STRING = 1.0 - LIBRARY_CLASS = CustomizedDisplayLib|DXE_DRIVER UEFI_APPLICATION - CONSTRUCTOR = CustomizedDisplayLibConstructor - DESTRUCTOR = CustomizedDisplayLibDestructor -# -# The following information is for reference only and not required by the build tools. -# -# VALID_ARCHITECTURES = IA32 X64 IPF EBC -# - -[Sources] - CustomizedDisplayLib.c - Colors.h - CustomizedDisplayLibInternal.h - CustomizedDisplayLibInternal.c - CustomizedDisplayLib.uni - -[Packages] - MdePkg/MdePkg.dec - MdeModulePkg/MdeModulePkg.dec - -[LibraryClasses] - MemoryAllocationLib - BaseLib - UefiBootServicesTableLib - UefiDriverEntryPoint - UefiRuntimeServicesTableLib - BaseMemoryLib - DebugLib - PrintLib - HiiLib - DevicePathLib - PcdLib - -[Guids] - gEfiIfrTianoGuid - -[Protocols] - -[Pcd] - gEfiMdeModulePkgTokenSpaceGuid.PcdBrowserSubtitleTextColor ## CONSUMES - gEfiMdeModulePkgTokenSpaceGuid.PcdBrowserFieldTextColor ## CONSUMES - gEfiMdeModulePkgTokenSpaceGuid.PcdBrowserFieldTextHighlightColor ## CONSUMES - gEfiMdeModulePkgTokenSpaceGuid.PcdBrowserFieldBackgroundHighlightColor ## CONSUMES \ No newline at end of file diff --git a/MdeModulePkg/Library/CustomizedDisplayLib/CustomizedDisplayLib.uni b/MdeModulePkg/Library/CustomizedDisplayLib/CustomizedDisplayLib.uni deleted file mode 100644 index 18a5c3b563..0000000000 Binary files a/MdeModulePkg/Library/CustomizedDisplayLib/CustomizedDisplayLib.uni and /dev/null differ diff --git a/MdeModulePkg/Library/CustomizedDisplayLib/CustomizedDisplayLibInternal.c b/MdeModulePkg/Library/CustomizedDisplayLib/CustomizedDisplayLibInternal.c deleted file mode 100644 index b6b4055b6d..0000000000 --- a/MdeModulePkg/Library/CustomizedDisplayLib/CustomizedDisplayLibInternal.c +++ /dev/null @@ -1,914 +0,0 @@ -/** @file - - This library class defines a set of interfaces to customize Display module - -Copyright (c) 2013, Intel Corporation. All rights reserved.
-This program and the accompanying materials are licensed and made available under -the terms and conditions of the BSD License that accompanies this distribution. -The full text of the license may be found at -http://opensource.org/licenses/bsd-license.php. - -THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, -WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. - -**/ -#include "CustomizedDisplayLibInternal.h" - -EFI_SCREEN_DESCRIPTOR gScreenDimensions; -CHAR16 *mLibUnknownString; -extern EFI_HII_HANDLE mCDLStringPackHandle; -CHAR16 *mSpaceBuffer; -#define SPACE_BUFFER_SIZE 1000 - -// -// Browser Global Strings -// -CHAR16 *gEnterString; -CHAR16 *gEnterCommitString; -CHAR16 *gEnterEscapeString; -CHAR16 *gEscapeString; -CHAR16 *gMoveHighlight; -CHAR16 *gDecNumericInput; -CHAR16 *gHexNumericInput; -CHAR16 *gToggleCheckBox; -CHAR16 *gLibEmptyString; -CHAR16 *gAreYouSure; -CHAR16 *gYesResponse; -CHAR16 *gNoResponse; -CHAR16 *gPlusString; -CHAR16 *gMinusString; -CHAR16 *gAdjustNumber; -CHAR16 *gSaveChanges; -CHAR16 *gNvUpdateMessage; -CHAR16 *gInputErrorMessage; - -/** - - Print banner info for front page. - - @param[in] FormData Form Data to be shown in Page - -**/ -VOID -PrintBannerInfo ( - IN FORM_DISPLAY_ENGINE_FORM *FormData - ) -{ - UINT8 Line; - UINT8 Alignment; - CHAR16 *StrFrontPageBanner; - UINT8 RowIdx; - UINT8 ColumnIdx; - - // - // ClearLines(0, LocalScreen.RightColumn, 0, BANNER_HEIGHT-1, BANNER_TEXT | BANNER_BACKGROUND); - // - ClearLines ( - gScreenDimensions.LeftColumn, - gScreenDimensions.RightColumn, - gScreenDimensions.TopRow, - FRONT_PAGE_HEADER_HEIGHT - 1 + gScreenDimensions.TopRow, - BANNER_TEXT | BANNER_BACKGROUND - ); - - // - // for (Line = 0; Line < BANNER_HEIGHT; Line++) { - // - for (Line = (UINT8) gScreenDimensions.TopRow; Line < BANNER_HEIGHT + (UINT8) gScreenDimensions.TopRow; Line++) { - // - // for (Alignment = 0; Alignment < BANNER_COLUMNS; Alignment++) { - // - for (Alignment = (UINT8) gScreenDimensions.LeftColumn; - Alignment < BANNER_COLUMNS + (UINT8) gScreenDimensions.LeftColumn; - Alignment++ - ) { - RowIdx = (UINT8) (Line - (UINT8) gScreenDimensions.TopRow); - ColumnIdx = (UINT8) (Alignment - (UINT8) gScreenDimensions.LeftColumn); - - ASSERT (RowIdx < BANNER_HEIGHT && ColumnIdx < BANNER_COLUMNS); - - if (gBannerData!= NULL && gBannerData->Banner[RowIdx][ColumnIdx] != 0x0000) { - StrFrontPageBanner = LibGetToken (gBannerData->Banner[RowIdx][ColumnIdx], FormData->HiiHandle); - } else { - continue; - } - - switch (Alignment - gScreenDimensions.LeftColumn) { - case 0: - // - // Handle left column - // - PrintStringAt (gScreenDimensions.LeftColumn + BANNER_LEFT_COLUMN_INDENT, Line, StrFrontPageBanner); - break; - - case 1: - // - // Handle center column - // - PrintStringAt ( - gScreenDimensions.LeftColumn + (gScreenDimensions.RightColumn - gScreenDimensions.LeftColumn) / 3, - Line, - StrFrontPageBanner - ); - break; - - case 2: - // - // Handle right column - // - PrintStringAt ( - gScreenDimensions.LeftColumn + (gScreenDimensions.RightColumn - gScreenDimensions.LeftColumn) * 2 / 3, - Line, - StrFrontPageBanner - ); - break; - } - - FreePool (StrFrontPageBanner); - } - } -} - -/** - Print framework and form title for a page. - - @param[in] FormData Form Data to be shown in Page -**/ -VOID -PrintFramework ( - IN FORM_DISPLAY_ENGINE_FORM *FormData - ) -{ - UINTN Index; - CHAR16 Character; - CHAR16 *Buffer; - UINTN Row; - CHAR16 *TitleStr; - - if (gClassOfVfr != FORMSET_CLASS_PLATFORM_SETUP) { - // - // Only Setup page needs Framework - // - ClearLines ( - gScreenDimensions.LeftColumn, - gScreenDimensions.RightColumn, - gScreenDimensions.BottomRow - STATUS_BAR_HEIGHT - gFooterHeight, - gScreenDimensions.BottomRow - STATUS_BAR_HEIGHT - 1, - KEYHELP_TEXT | KEYHELP_BACKGROUND - ); - return; - } - - Buffer = AllocateZeroPool (0x10000); - ASSERT (Buffer != NULL); - Character = BOXDRAW_HORIZONTAL; - for (Index = 0; Index + 2 < (gScreenDimensions.RightColumn - gScreenDimensions.LeftColumn); Index++) { - Buffer[Index] = Character; - } - - // - // Print Top border line - // +------------------------------------------------------------------------------+ - // ? ? - // +------------------------------------------------------------------------------+ - // - gST->ConOut->SetAttribute (gST->ConOut, TITLE_TEXT | TITLE_BACKGROUND); - Character = BOXDRAW_DOWN_RIGHT; - - PrintCharAt (gScreenDimensions.LeftColumn, gScreenDimensions.TopRow, Character); - PrintStringAt ((UINTN) -1, (UINTN) -1, Buffer); - - Character = BOXDRAW_DOWN_LEFT; - PrintCharAt ((UINTN) -1, (UINTN) -1, Character); - - Character = BOXDRAW_VERTICAL; - for (Row = gScreenDimensions.TopRow + 1; Row <= gScreenDimensions.TopRow + NONE_FRONT_PAGE_HEADER_HEIGHT - 2; Row++) { - PrintCharAt (gScreenDimensions.LeftColumn, Row, Character); - PrintCharAt (gScreenDimensions.RightColumn - 1, Row, Character); - } - - // - // Print Form Title - // - ClearLines ( - gScreenDimensions.LeftColumn + 1, - gScreenDimensions.RightColumn - 1, - gScreenDimensions.TopRow + 1, - gScreenDimensions.TopRow + 1, - TITLE_TEXT | TITLE_BACKGROUND - ); - - TitleStr = LibGetToken (FormData->FormTitle, FormData->HiiHandle); - ASSERT (TitleStr != NULL); - PrintStringAt ( - (gScreenDimensions.RightColumn + gScreenDimensions.LeftColumn - LibGetStringWidth (TitleStr) / 2) / 2, - gScreenDimensions.TopRow + 1, - TitleStr - ); - FreePool (TitleStr); - - Character = BOXDRAW_UP_RIGHT; - PrintCharAt (gScreenDimensions.LeftColumn, gScreenDimensions.TopRow + NONE_FRONT_PAGE_HEADER_HEIGHT - 1, Character); - PrintStringAt ((UINTN) -1, (UINTN) -1, Buffer); - - Character = BOXDRAW_UP_LEFT; - PrintCharAt ((UINTN) -1, (UINTN) -1, Character); - - // - // Print Bottom border line - // +------------------------------------------------------------------------------+ - // ? ? - // +------------------------------------------------------------------------------+ - // - Character = BOXDRAW_DOWN_RIGHT; - PrintCharAt (gScreenDimensions.LeftColumn, gScreenDimensions.BottomRow - STATUS_BAR_HEIGHT - gFooterHeight, Character); - - PrintStringAt ((UINTN) -1, (UINTN) -1, Buffer); - - Character = BOXDRAW_DOWN_LEFT; - PrintCharAt ((UINTN) -1, (UINTN) -1, Character); - Character = BOXDRAW_VERTICAL; - for (Row = gScreenDimensions.BottomRow - STATUS_BAR_HEIGHT - gFooterHeight + 1; - Row <= gScreenDimensions.BottomRow - STATUS_BAR_HEIGHT - 2; - Row++ - ) { - PrintCharAt (gScreenDimensions.LeftColumn, Row, Character); - PrintCharAt (gScreenDimensions.RightColumn - 1, Row, Character); - } - - Character = BOXDRAW_UP_RIGHT; - PrintCharAt (gScreenDimensions.LeftColumn, gScreenDimensions.BottomRow - STATUS_BAR_HEIGHT - 1, Character); - - PrintStringAt ((UINTN) -1, (UINTN) -1, Buffer); - - Character = BOXDRAW_UP_LEFT; - PrintCharAt ((UINTN) -1, (UINTN) -1, Character); - - FreePool (Buffer); -} - -/** - Process some op code which is not recognized by browser core. - - @param OpCodeData The pointer to the op code buffer. - - @return EFI_SUCCESS Pass the statement success. - -**/ -VOID -ProcessUserOpcode( - IN EFI_IFR_OP_HEADER *OpCodeData - ) -{ - switch (OpCodeData->OpCode) { - case EFI_IFR_GUID_OP: - if (CompareGuid (&gEfiIfrTianoGuid, (EFI_GUID *)((CHAR8*) OpCodeData + sizeof (EFI_IFR_OP_HEADER)))) { - // - // Tiano specific GUIDed opcodes - // - switch (((EFI_IFR_GUID_LABEL *) OpCodeData)->ExtendOpCode) { - case EFI_IFR_EXTEND_OP_LABEL: - // - // just ignore label - // - break; - - case EFI_IFR_EXTEND_OP_BANNER: - // - // Only in front page form set, we care about the banner data. - // - if (gClassOfVfr == FORMSET_CLASS_FRONT_PAGE) { - // - // Initialize Driver private data - // - if (gBannerData == NULL) { - gBannerData = AllocateZeroPool (sizeof (BANNER_DATA)); - ASSERT (gBannerData != NULL); - } - - CopyMem ( - &gBannerData->Banner[((EFI_IFR_GUID_BANNER *) OpCodeData)->LineNumber][ - ((EFI_IFR_GUID_BANNER *) OpCodeData)->Alignment], - &((EFI_IFR_GUID_BANNER *) OpCodeData)->Title, - sizeof (EFI_STRING_ID) - ); - } - break; - - case EFI_IFR_EXTEND_OP_SUBCLASS: - if (((EFI_IFR_GUID_SUBCLASS *) OpCodeData)->SubClass == EFI_FRONT_PAGE_SUBCLASS) { - gClassOfVfr = FORMSET_CLASS_FRONT_PAGE; - } - break; - - default: - break; - } - } - break; - - default: - break; - } -} - -/** - Process some op codes which is out side of current form. - - @param FormData Pointer to the form data. - - @return EFI_SUCCESS Pass the statement success. - -**/ -VOID -ProcessExternedOpcode ( - IN FORM_DISPLAY_ENGINE_FORM *FormData - ) -{ - LIST_ENTRY *Link; - FORM_DISPLAY_ENGINE_STATEMENT *Statement; - - Link = GetFirstNode (&FormData->StatementListOSF); - while (!IsNull (&FormData->StatementListOSF, Link)) { - Statement = FORM_DISPLAY_ENGINE_STATEMENT_FROM_LINK (Link); - Link = GetNextNode (&FormData->StatementListOSF, Link); - - ProcessUserOpcode(Statement->OpCode); - } - - Link = GetFirstNode (&FormData->StatementListHead); - while (!IsNull (&FormData->StatementListHead, Link)) { - Statement = FORM_DISPLAY_ENGINE_STATEMENT_FROM_LINK (Link); - Link = GetNextNode (&FormData->StatementListHead, Link); - - ProcessUserOpcode(Statement->OpCode); - } -} - -/** - Validate the input screen diemenstion info. - - @param FormData The input form data info. - - @return EFI_SUCCESS The input screen info is acceptable. - @return EFI_INVALID_PARAMETER The input screen info is not acceptable. - -**/ -EFI_STATUS -ScreenDiemensionInfoValidate ( - IN FORM_DISPLAY_ENGINE_FORM *FormData - ) -{ - LIST_ENTRY *Link; - UINTN Index; - - // - // Calculate total number of Register HotKeys. - // - Index = 0; - if (!IsListEmpty (&FormData->HotKeyListHead)){ - Link = GetFirstNode (&FormData->HotKeyListHead); - while (!IsNull (&FormData->HotKeyListHead, Link)) { - Link = GetNextNode (&FormData->HotKeyListHead, Link); - Index ++; - } - } - - // - // Show three HotKeys help information on one row. - // - gFooterHeight = FOOTER_HEIGHT + (Index / 3); - - - ZeroMem (&gScreenDimensions, sizeof (EFI_SCREEN_DESCRIPTOR)); - gST->ConOut->QueryMode ( - gST->ConOut, - gST->ConOut->Mode->Mode, - &gScreenDimensions.RightColumn, - &gScreenDimensions.BottomRow - ); - - // - // Check local dimension vs. global dimension. - // - if (FormData->ScreenDimensions != NULL) { - if ((gScreenDimensions.RightColumn < FormData->ScreenDimensions->RightColumn) || - (gScreenDimensions.BottomRow < FormData->ScreenDimensions->BottomRow) - ) { - return EFI_INVALID_PARAMETER; - } else { - // - // Local dimension validation. - // - if ((FormData->ScreenDimensions->RightColumn > FormData->ScreenDimensions->LeftColumn) && - (FormData->ScreenDimensions->BottomRow > FormData->ScreenDimensions->TopRow) && - ((FormData->ScreenDimensions->RightColumn - FormData->ScreenDimensions->LeftColumn) > 2) && - ((FormData->ScreenDimensions->BottomRow - FormData->ScreenDimensions->TopRow) > STATUS_BAR_HEIGHT + - FRONT_PAGE_HEADER_HEIGHT + gFooterHeight + 3)) { - CopyMem (&gScreenDimensions, (VOID *) FormData->ScreenDimensions, sizeof (EFI_SCREEN_DESCRIPTOR)); - } else { - return EFI_INVALID_PARAMETER; - } - } - } - - return EFI_SUCCESS; -} - -/** - Get the string based on the StringId and HII Package List Handle. - - @param Token The String's ID. - @param HiiHandle The package list in the HII database to search for - the specified string. - - @return The output string. - -**/ -CHAR16 * -LibGetToken ( - IN EFI_STRING_ID Token, - IN EFI_HII_HANDLE HiiHandle - ) -{ - EFI_STRING String; - - String = HiiGetString (HiiHandle, Token, NULL); - if (String == NULL) { - String = AllocateCopyPool (StrSize (mLibUnknownString), mLibUnknownString); - ASSERT (String != NULL); - } - - return (CHAR16 *) String; -} - - -/** - Count the storage space of a Unicode string. - - This function handles the Unicode string with NARROW_CHAR - and WIDE_CHAR control characters. NARROW_HCAR and WIDE_CHAR - does not count in the resultant output. If a WIDE_CHAR is - hit, then 2 Unicode character will consume an output storage - space with size of CHAR16 till a NARROW_CHAR is hit. - - If String is NULL, then ASSERT (). - - @param String The input string to be counted. - - @return Storage space for the input string. - -**/ -UINTN -LibGetStringWidth ( - IN CHAR16 *String - ) -{ - UINTN Index; - UINTN Count; - UINTN IncrementValue; - - ASSERT (String != NULL); - if (String == NULL) { - return 0; - } - - Index = 0; - Count = 0; - IncrementValue = 1; - - do { - // - // Advance to the null-terminator or to the first width directive - // - for (; - (String[Index] != NARROW_CHAR) && (String[Index] != WIDE_CHAR) && (String[Index] != 0); - Index++, Count = Count + IncrementValue - ) - ; - - // - // We hit the null-terminator, we now have a count - // - if (String[Index] == 0) { - break; - } - // - // We encountered a narrow directive - strip it from the size calculation since it doesn't get printed - // and also set the flag that determines what we increment by.(if narrow, increment by 1, if wide increment by 2) - // - if (String[Index] == NARROW_CHAR) { - // - // Skip to the next character - // - Index++; - IncrementValue = 1; - } else { - // - // Skip to the next character - // - Index++; - IncrementValue = 2; - } - } while (String[Index] != 0); - - // - // Increment by one to include the null-terminator in the size - // - Count++; - - return Count * sizeof (CHAR16); -} - -/** - Show all registered HotKey help strings on bottom Rows. - - @param FormData The curent input form data info. - -**/ -VOID -PrintHotKeyHelpString ( - IN FORM_DISPLAY_ENGINE_FORM *FormData - ) -{ - UINTN CurrentCol; - UINTN CurrentRow; - UINTN BottomRowOfHotKeyHelp; - UINTN ColumnWidth; - UINTN Index; - EFI_SCREEN_DESCRIPTOR LocalScreen; - LIST_ENTRY *Link; - BROWSER_HOT_KEY *HotKey; - - if (IsListEmpty (&FormData->HotKeyListHead)) { - return; - } - - CopyMem (&LocalScreen, &gScreenDimensions, sizeof (EFI_SCREEN_DESCRIPTOR)); - ColumnWidth = (LocalScreen.RightColumn - LocalScreen.LeftColumn) / 3; - BottomRowOfHotKeyHelp = LocalScreen.BottomRow - STATUS_BAR_HEIGHT - 3; - - // - // Calculate total number of Register HotKeys. - // - Index = 0; - Link = GetFirstNode (&FormData->HotKeyListHead); - while (!IsNull (&FormData->HotKeyListHead, Link)) { - HotKey = BROWSER_HOT_KEY_FROM_LINK (Link); - // - // Help string can't exceed ColumnWidth. One Row will show three Help information. - // - if (StrLen (HotKey->HelpString) > ColumnWidth) { - HotKey->HelpString[ColumnWidth] = L'\0'; - } - // - // Calculate help information Column and Row. - // - if ((Index % 3) != 2) { - CurrentCol = LocalScreen.LeftColumn + (2 - Index % 3) * ColumnWidth; - } else { - CurrentCol = LocalScreen.LeftColumn + 2; - } - CurrentRow = BottomRowOfHotKeyHelp - Index / 3; - // - // Print HotKey help string on bottom Row. - // - PrintStringAt (CurrentCol, CurrentRow, HotKey->HelpString); - - // - // Get Next Hot Key. - // - Link = GetNextNode (&FormData->HotKeyListHead, Link); - Index ++; - } - - return; -} - -/** - Get step info from numeric opcode. - - @param[in] OpCode The input numeric op code. - - @return step info for this opcode. -**/ -UINT64 -LibGetFieldFromNum ( - IN EFI_IFR_OP_HEADER *OpCode - ) -{ - EFI_IFR_NUMERIC *NumericOp; - UINT64 Step; - - NumericOp = (EFI_IFR_NUMERIC *) OpCode; - - switch (NumericOp->Flags & EFI_IFR_NUMERIC_SIZE) { - case EFI_IFR_NUMERIC_SIZE_1: - Step = NumericOp->data.u8.Step; - break; - - case EFI_IFR_NUMERIC_SIZE_2: - Step = NumericOp->data.u16.Step; - break; - - case EFI_IFR_NUMERIC_SIZE_4: - Step = NumericOp->data.u32.Step; - break; - - case EFI_IFR_NUMERIC_SIZE_8: - Step = NumericOp->data.u64.Step; - break; - - default: - Step = 0; - break; - } - - return Step; -} - -/** - Initialize the HII String Token to the correct values. - -**/ -VOID -InitializeLibStrings ( - VOID - ) -{ - mLibUnknownString = L"!"; - - gEnterString = LibGetToken (STRING_TOKEN (ENTER_STRING), mCDLStringPackHandle); - gEnterCommitString = LibGetToken (STRING_TOKEN (ENTER_COMMIT_STRING), mCDLStringPackHandle); - gEnterEscapeString = LibGetToken (STRING_TOKEN (ENTER_ESCAPE_STRING), mCDLStringPackHandle); - gEscapeString = LibGetToken (STRING_TOKEN (ESCAPE_STRING), mCDLStringPackHandle); - gMoveHighlight = LibGetToken (STRING_TOKEN (MOVE_HIGHLIGHT), mCDLStringPackHandle); - gDecNumericInput = LibGetToken (STRING_TOKEN (DEC_NUMERIC_INPUT), mCDLStringPackHandle); - gHexNumericInput = LibGetToken (STRING_TOKEN (HEX_NUMERIC_INPUT), mCDLStringPackHandle); - gToggleCheckBox = LibGetToken (STRING_TOKEN (TOGGLE_CHECK_BOX), mCDLStringPackHandle); - - gAreYouSure = LibGetToken (STRING_TOKEN (ARE_YOU_SURE), mCDLStringPackHandle); - gYesResponse = LibGetToken (STRING_TOKEN (ARE_YOU_SURE_YES), mCDLStringPackHandle); - gNoResponse = LibGetToken (STRING_TOKEN (ARE_YOU_SURE_NO), mCDLStringPackHandle); - gPlusString = LibGetToken (STRING_TOKEN (PLUS_STRING), mCDLStringPackHandle); - gMinusString = LibGetToken (STRING_TOKEN (MINUS_STRING), mCDLStringPackHandle); - gAdjustNumber = LibGetToken (STRING_TOKEN (ADJUST_NUMBER), mCDLStringPackHandle); - gSaveChanges = LibGetToken (STRING_TOKEN (SAVE_CHANGES), mCDLStringPackHandle); - - gLibEmptyString = LibGetToken (STRING_TOKEN (EMPTY_STRING), mCDLStringPackHandle); - - gNvUpdateMessage = LibGetToken (STRING_TOKEN (NV_UPDATE_MESSAGE), mCDLStringPackHandle); - gInputErrorMessage = LibGetToken (STRING_TOKEN (INPUT_ERROR_MESSAGE), mCDLStringPackHandle); - - // - // SpaceBuffer; - // - mSpaceBuffer = AllocatePool ((SPACE_BUFFER_SIZE + 1) * sizeof (CHAR16)); - ASSERT (mSpaceBuffer != NULL); - LibSetUnicodeMem (mSpaceBuffer, SPACE_BUFFER_SIZE, L' '); - mSpaceBuffer[SPACE_BUFFER_SIZE] = L'\0'; -} - - -/** - Free the HII String. - -**/ -VOID -FreeLibStrings ( - VOID - ) -{ - FreePool (gEnterString); - FreePool (gEnterCommitString); - FreePool (gEnterEscapeString); - FreePool (gEscapeString); - FreePool (gMoveHighlight); - FreePool (gDecNumericInput); - FreePool (gHexNumericInput); - FreePool (gToggleCheckBox); - - FreePool (gAreYouSure); - FreePool (gYesResponse); - FreePool (gNoResponse); - FreePool (gPlusString); - FreePool (gMinusString); - FreePool (gAdjustNumber); - FreePool (gSaveChanges); - - FreePool (gLibEmptyString); - - FreePool (gNvUpdateMessage); - FreePool (gInputErrorMessage); - - FreePool (mSpaceBuffer); -} - -/** - Wait for a key to be pressed by user. - - @param Key The key which is pressed by user. - - @retval EFI_SUCCESS The function always completed successfully. - -**/ -EFI_STATUS -WaitForKeyStroke ( - OUT EFI_INPUT_KEY *Key - ) -{ - EFI_STATUS Status; - UINTN Index; - - while (TRUE) { - Status = gST->ConIn->ReadKeyStroke (gST->ConIn, Key); - if (!EFI_ERROR (Status)) { - break; - } - - if (Status != EFI_NOT_READY) { - continue; - } - - gBS->WaitForEvent (1, &gST->ConIn->WaitForKey, &Index); - } - return Status; -} - - -/** - Set Buffer to Value for Size bytes. - - @param Buffer Memory to set. - @param Size Number of bytes to set - @param Value Value of the set operation. - -**/ -VOID -LibSetUnicodeMem ( - IN VOID *Buffer, - IN UINTN Size, - IN CHAR16 Value - ) -{ - CHAR16 *Ptr; - - Ptr = Buffer; - while ((Size--) != 0) { - *(Ptr++) = Value; - } -} - -/** - The internal function prints to the EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL - protocol instance. - - @param Width Width of string to be print. - @param Column The position of the output string. - @param Row The position of the output string. - @param Out The EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL instance. - @param Fmt The format string. - @param Args The additional argument for the variables in the format string. - - @return Number of Unicode character printed. - -**/ -UINTN -PrintInternal ( - IN UINTN Width, - IN UINTN Column, - IN UINTN Row, - IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *Out, - IN CHAR16 *Fmt, - IN VA_LIST Args - ) -{ - CHAR16 *Buffer; - CHAR16 *BackupBuffer; - UINTN Index; - UINTN PreviousIndex; - UINTN Count; - UINTN PrintWidth; - UINTN CharWidth; - - // - // For now, allocate an arbitrarily long buffer - // - Buffer = AllocateZeroPool (0x10000); - BackupBuffer = AllocateZeroPool (0x10000); - ASSERT (Buffer); - ASSERT (BackupBuffer); - - if (Column != (UINTN) -1) { - Out->SetCursorPosition (Out, Column, Row); - } - - UnicodeVSPrint (Buffer, 0x10000, Fmt, Args); - - Out->Mode->Attribute = Out->Mode->Attribute & 0x7f; - - Out->SetAttribute (Out, Out->Mode->Attribute); - - Index = 0; - PreviousIndex = 0; - Count = 0; - PrintWidth = 0; - CharWidth = 1; - - do { - for (; (Buffer[Index] != NARROW_CHAR) && (Buffer[Index] != WIDE_CHAR) && (Buffer[Index] != 0); Index++) { - BackupBuffer[Index] = Buffer[Index]; - } - - if (Buffer[Index] == 0) { - break; - } - // - // Null-terminate the temporary string - // - BackupBuffer[Index] = 0; - - // - // Print this out, we are about to switch widths - // - Out->OutputString (Out, &BackupBuffer[PreviousIndex]); - Count += StrLen (&BackupBuffer[PreviousIndex]); - PrintWidth += Count * CharWidth; - - // - // Preserve the current index + 1, since this is where we will start printing from next - // - PreviousIndex = Index + 1; - - // - // We are at a narrow or wide character directive. Set attributes and strip it and print it - // - if (Buffer[Index] == NARROW_CHAR) { - // - // Preserve bits 0 - 6 and zero out the rest - // - Out->Mode->Attribute = Out->Mode->Attribute & 0x7f; - Out->SetAttribute (Out, Out->Mode->Attribute); - CharWidth = 1; - } else { - // - // Must be wide, set bit 7 ON - // - Out->Mode->Attribute = Out->Mode->Attribute | EFI_WIDE_ATTRIBUTE; - Out->SetAttribute (Out, Out->Mode->Attribute); - CharWidth = 2; - } - - Index++; - - } while (Buffer[Index] != 0); - - // - // We hit the end of the string - print it - // - Out->OutputString (Out, &BackupBuffer[PreviousIndex]); - Count += StrLen (&BackupBuffer[PreviousIndex]); - PrintWidth += Count * CharWidth; - if (PrintWidth < Width) { - Out->Mode->Attribute = Out->Mode->Attribute & 0x7f; - Out->SetAttribute (Out, Out->Mode->Attribute); - Out->OutputString (Out, &mSpaceBuffer[SPACE_BUFFER_SIZE - Width + PrintWidth]); - } - - FreePool (Buffer); - FreePool (BackupBuffer); - return Count; -} - -/** - Prints a formatted unicode string to the default console, at - the supplied cursor position. - - @param Width Width of String to be printed. - @param Column The cursor position to print the string at. - @param Row The cursor position to print the string at. - @param Fmt Format string. - @param ... Variable argument list for format string. - - @return Length of string printed to the console - -**/ -UINTN -EFIAPI -PrintAt ( - IN UINTN Width, - IN UINTN Column, - IN UINTN Row, - IN CHAR16 *Fmt, - ... - ) -{ - VA_LIST Args; - UINTN LengthOfPrinted; - - VA_START (Args, Fmt); - LengthOfPrinted = PrintInternal (Width, Column, Row, gST->ConOut, Fmt, Args); - VA_END (Args); - return LengthOfPrinted; -} - diff --git a/MdeModulePkg/Library/CustomizedDisplayLib/CustomizedDisplayLibInternal.h b/MdeModulePkg/Library/CustomizedDisplayLib/CustomizedDisplayLibInternal.h deleted file mode 100644 index ccbd45f425..0000000000 --- a/MdeModulePkg/Library/CustomizedDisplayLib/CustomizedDisplayLibInternal.h +++ /dev/null @@ -1,295 +0,0 @@ -/** @file - - This library class defines a set of interfaces to customize Display module - -Copyright (c) 2013, Intel Corporation. All rights reserved.
-This program and the accompanying materials are licensed and made available under -the terms and conditions of the BSD License that accompanies this distribution. -The full text of the license may be found at -http://opensource.org/licenses/bsd-license.php. - -THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, -WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. - -**/ - -#ifndef __CUSTOMIZED_DISPLAY_LIB_INTERNAL_H__ -#define __CUSTOMIZED_DISPLAY_LIB_INTERNAL_H__ - - - -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "Colors.h" - - - -#define FORMSET_CLASS_PLATFORM_SETUP 0x0001 -#define FORMSET_CLASS_FRONT_PAGE 0x0002 - - -#define FRONT_PAGE_HEADER_HEIGHT 6 -#define NONE_FRONT_PAGE_HEADER_HEIGHT 3 -#define FOOTER_HEIGHT 4 -#define STATUS_BAR_HEIGHT 1 - -// -// Screen definitions -// -#define BANNER_HEIGHT 6 -#define BANNER_COLUMNS 3 -#define BANNER_LEFT_COLUMN_INDENT 1 - -// -// Character definitions -// -#define UPPER_LOWER_CASE_OFFSET 0x20 - -// -// This is the Input Error Message -// -#define INPUT_ERROR 1 - -// -// This is the NV RAM update required Message -// -#define NV_UPDATE_REQUIRED 2 - -typedef struct { - EFI_STRING_ID Banner[BANNER_HEIGHT][BANNER_COLUMNS]; -} BANNER_DATA; - -extern UINT16 gClassOfVfr; // Formset class information -extern BANNER_DATA *gBannerData; -extern EFI_SCREEN_DESCRIPTOR gScreenDimensions; -extern UINTN gFooterHeight; - -// -// Browser Global Strings -// -extern CHAR16 *gEnterString; -extern CHAR16 *gEnterCommitString; -extern CHAR16 *gEnterEscapeString; -extern CHAR16 *gEscapeString; -extern CHAR16 *gMoveHighlight; -extern CHAR16 *gDecNumericInput; -extern CHAR16 *gHexNumericInput; -extern CHAR16 *gToggleCheckBox; -extern CHAR16 *gLibEmptyString; -extern CHAR16 *gAreYouSure; -extern CHAR16 *gYesResponse; -extern CHAR16 *gNoResponse; -extern CHAR16 *gPlusString; -extern CHAR16 *gMinusString; -extern CHAR16 *gAdjustNumber; -extern CHAR16 *gSaveChanges; -extern CHAR16 *gNvUpdateMessage; -extern CHAR16 *gInputErrorMessage; -/** - - Print banner info for front page. - - @param[in] FormData Form Data to be shown in Page - -**/ -VOID -PrintBannerInfo ( - IN FORM_DISPLAY_ENGINE_FORM *FormData - ); - -/** - Print framework and form title for a page. - - @param[in] FormData Form Data to be shown in Page -**/ -VOID -PrintFramework ( - IN FORM_DISPLAY_ENGINE_FORM *FormData - ); - -/** - Validate the input screen diemenstion info. - - @param FormData The input form data info. - - @return EFI_SUCCESS The input screen info is acceptable. - @return EFI_INVALID_PARAMETER The input screen info is not acceptable. - -**/ -EFI_STATUS -ScreenDiemensionInfoValidate ( - IN FORM_DISPLAY_ENGINE_FORM *FormData - ); - -/** - Get the string based on the StringId and HII Package List Handle. - - @param Token The String's ID. - @param HiiHandle The package list in the HII database to search for - the specified string. - - @return The output string. - -**/ -CHAR16 * -LibGetToken ( - IN EFI_STRING_ID Token, - IN EFI_HII_HANDLE HiiHandle - ); - -/** - Count the storage space of a Unicode string. - - This function handles the Unicode string with NARROW_CHAR - and WIDE_CHAR control characters. NARROW_HCAR and WIDE_CHAR - does not count in the resultant output. If a WIDE_CHAR is - hit, then 2 Unicode character will consume an output storage - space with size of CHAR16 till a NARROW_CHAR is hit. - - If String is NULL, then ASSERT (). - - @param String The input string to be counted. - - @return Storage space for the input string. - -**/ -UINTN -LibGetStringWidth ( - IN CHAR16 *String - ); - -/** - Show all registered HotKey help strings on bottom Rows. - - @param FormData The curent input form data info. - -**/ -VOID -PrintHotKeyHelpString ( - IN FORM_DISPLAY_ENGINE_FORM *FormData - ); - -/** - Get step info from numeric opcode. - - @param[in] OpCode The input numeric op code. - - @return step info for this opcode. -**/ -UINT64 -LibGetFieldFromNum ( - IN EFI_IFR_OP_HEADER *OpCode - ); - -/** - Initialize the HII String Token to the correct values. - -**/ -VOID -InitializeLibStrings ( - VOID - ); - -/** - Free the HII String. - -**/ -VOID -FreeLibStrings ( - VOID - ); - -/** - Wait for a key to be pressed by user. - - @param Key The key which is pressed by user. - - @retval EFI_SUCCESS The function always completed successfully. - -**/ -EFI_STATUS -WaitForKeyStroke ( - OUT EFI_INPUT_KEY *Key - ); - -/** - Set Buffer to Value for Size bytes. - - @param Buffer Memory to set. - @param Size Number of bytes to set - @param Value Value of the set operation. - -**/ -VOID -LibSetUnicodeMem ( - IN VOID *Buffer, - IN UINTN Size, - IN CHAR16 Value - ); - -/** - Prints a formatted unicode string to the default console, at - the supplied cursor position. - - @param Width Width of String to be printed. - @param Column The cursor position to print the string at. - @param Row The cursor position to print the string at. - @param Fmt Format string. - @param ... Variable argument list for format string. - - @return Length of string printed to the console - -**/ -UINTN -EFIAPI -PrintAt ( - IN UINTN Width, - IN UINTN Column, - IN UINTN Row, - IN CHAR16 *Fmt, - ... - ); - -/** - Process some op codes which is out side of current form. - - @param FormData Pointer to the form data. - -**/ -VOID -ProcessExternedOpcode ( - IN FORM_DISPLAY_ENGINE_FORM *FormData - ); - -#endif diff --git a/MdeModulePkg/MdeModulePkg.dec b/MdeModulePkg/MdeModulePkg.dec index 4ae24eb80e..3105519297 100644 --- a/MdeModulePkg/MdeModulePkg.dec +++ b/MdeModulePkg/MdeModulePkg.dec @@ -98,10 +98,6 @@ # CpuExceptionHandlerLib|Include/Library/CpuExceptionHandlerLib.h - ## @libraryclass Provides platform specific display interface. - # - CustomizedDisplayLib|Include/Library/CustomizedDisplayLib.h - [Guids] ## MdeModule package token space guid # Include/Guid/MdeModulePkgTokenSpace.h @@ -365,12 +361,6 @@ ## Include/Protocol/BootLogo.h gEfiBootLogoProtocolGuid = { 0xcdea2bd3, 0xfc25, 0x4c1c, { 0xb9, 0x7c, 0xb3, 0x11, 0x86, 0x6, 0x49, 0x90 } } - ## Include/Protocol/DisplayProtocol.h - gEdkiiFormDisplayEngineProtocolGuid = { 0x9bbe29e9, 0xfda1, 0x41ec, { 0xad, 0x52, 0x45, 0x22, 0x13, 0x74, 0x2d, 0x2e } } - - ## Include/Protocol/FormBrowserEx2.h - gEdkiiFormBrowserEx2ProtocolGuid = { 0xa770c357, 0xb693, 0x4e6d, { 0xa6, 0xcf, 0xd2, 0x1c, 0x72, 0x8e, 0x55, 0xb } } - [PcdsFeatureFlag] ## Indicate whether platform can support update capsule across a system reset gEfiMdeModulePkgTokenSpaceGuid.PcdSupportUpdateCapsuleReset|FALSE|BOOLEAN|0x0001001d diff --git a/MdeModulePkg/MdeModulePkg.dsc b/MdeModulePkg/MdeModulePkg.dsc index 7895834c24..781fbbf3b4 100644 --- a/MdeModulePkg/MdeModulePkg.dsc +++ b/MdeModulePkg/MdeModulePkg.dsc @@ -76,7 +76,6 @@ CapsuleLib|MdeModulePkg/Library/DxeCapsuleLibNull/DxeCapsuleLibNull.inf PcdLib|MdePkg/Library/BasePcdLibNull/BasePcdLibNull.inf PalLib|MdePkg/Library/BasePalLibNull/BasePalLibNull.inf - CustomizedDisplayLib|MdeModulePkg/Library/CustomizedDisplayLib/CustomizedDisplayLib.inf # # Misc # @@ -294,7 +293,6 @@ MdeModulePkg/Universal/SecurityStubDxe/SecurityStubDxe.inf MdeModulePkg/Universal/SetupBrowserDxe/SetupBrowserDxe.inf - MdeModulePkg/Universal/DisplayEngineDxe/DisplayEngineDxe.inf MdeModulePkg/Application/VariableInfo/VariableInfo.inf MdeModulePkg/Universal/FaultTolerantWritePei/FaultTolerantWritePei.inf MdeModulePkg/Universal/Variable/Pei/VariablePei.inf diff --git a/MdeModulePkg/Universal/DisplayEngineDxe/DisplayEngineDxe.inf b/MdeModulePkg/Universal/DisplayEngineDxe/DisplayEngineDxe.inf deleted file mode 100644 index 323fcadb85..0000000000 --- a/MdeModulePkg/Universal/DisplayEngineDxe/DisplayEngineDxe.inf +++ /dev/null @@ -1,66 +0,0 @@ -## @file -# The DXE driver produces FORM BROWSER protocols defined in UEFI HII 2.1 specificatin. -# -# Copyright (c) 2007 - 2013, Intel Corporation. All rights reserved.
-# -# This program and the accompanying materials -# are licensed and made available under the terms and conditions of the BSD License -# which accompanies this distribution. The full text of the license may be found at -# http://opensource.org/licenses/bsd-license.php -# -# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, -# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. -# -# -## - -[Defines] - INF_VERSION = 0x00010005 - BASE_NAME = DisplayEngine - FILE_GUID = E660EA85-058E-4b55-A54B-F02F83A24707 - MODULE_TYPE = DXE_DRIVER - VERSION_STRING = 1.0 - ENTRY_POINT = InitializeDisplayEngine - UNLOAD_IMAGE = UnloadDisplayEngine -# -# The following information is for reference only and not required by the build tools. -# -# VALID_ARCHITECTURES = IA32 X64 IPF EBC -# - -[Sources] - FormDisplayStr.uni - FormDisplay.c - FormDisplay.h - ProcessOptions.c - InputHandler.c - -[Packages] - MdePkg/MdePkg.dec - MdeModulePkg/MdeModulePkg.dec - -[LibraryClasses] - UefiDriverEntryPoint - UefiBootServicesTableLib - DebugLib - BaseMemoryLib - BaseLib - PrintLib - HiiLib - MemoryAllocationLib - CustomizedDisplayLib - -[Protocols] - gEdkiiFormDisplayEngineProtocolGuid - gEdkiiFormBrowserEx2ProtocolGuid - -[Guids] - gEfiIfrTianoGuid ## CONSUMES ## GUID - -[Depex] - gEfiHiiDatabaseProtocolGuid AND gEfiHiiConfigRoutingProtocolGuid AND gEdkiiFormBrowserEx2ProtocolGuid - -[FeaturePcd] - gEfiMdeModulePkgTokenSpaceGuid.PcdBrowserGrayOutTextStatement ## CONSUMES - gEfiMdeModulePkgTokenSpaceGuid.PcdBrowerGrayOutReadOnlyMenu ## CONSUMES - diff --git a/MdeModulePkg/Universal/DisplayEngineDxe/FormDisplay.c b/MdeModulePkg/Universal/DisplayEngineDxe/FormDisplay.c deleted file mode 100644 index a07cc75a47..0000000000 --- a/MdeModulePkg/Universal/DisplayEngineDxe/FormDisplay.c +++ /dev/null @@ -1,3255 +0,0 @@ -/** @file -Entry and initialization module for the browser. - -Copyright (c) 2007 - 2013, Intel Corporation. All rights reserved.
-This program and the accompanying materials -are licensed and made available under the terms and conditions of the BSD License -which accompanies this distribution. The full text of the license may be found at -http://opensource.org/licenses/bsd-license.php - -THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, -WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. - -**/ - -#include "FormDisplay.h" - -// -// Search table for UiDisplayMenu() -// -SCAN_CODE_TO_SCREEN_OPERATION gScanCodeToOperation[] = { - { - SCAN_UP, - UiUp, - }, - { - SCAN_DOWN, - UiDown, - }, - { - SCAN_PAGE_UP, - UiPageUp, - }, - { - SCAN_PAGE_DOWN, - UiPageDown, - }, - { - SCAN_ESC, - UiReset, - }, - { - SCAN_LEFT, - UiLeft, - }, - { - SCAN_RIGHT, - UiRight, - } -}; - -UINTN mScanCodeNumber = sizeof (gScanCodeToOperation) / sizeof (gScanCodeToOperation[0]); - -SCREEN_OPERATION_T0_CONTROL_FLAG gScreenOperationToControlFlag[] = { - { - UiNoOperation, - CfUiNoOperation, - }, - { - UiSelect, - CfUiSelect, - }, - { - UiUp, - CfUiUp, - }, - { - UiDown, - CfUiDown, - }, - { - UiLeft, - CfUiLeft, - }, - { - UiRight, - CfUiRight, - }, - { - UiReset, - CfUiReset, - }, - { - UiPageUp, - CfUiPageUp, - }, - { - UiPageDown, - CfUiPageDown - }, - { - UiHotKey, - CfUiHotKey - } -}; - -EFI_GUID gDisplayEngineGuid = { - 0xE38C1029, 0xE38F, 0x45b9, {0x8F, 0x0D, 0xE2, 0xE6, 0x0B, 0xC9, 0xB2, 0x62} -}; - -FORM_ENTRY_INFO gFormEntryInfo; -UINTN gSequence; -EFI_SCREEN_DESCRIPTOR gStatementDimensions; -BOOLEAN mStatementLayoutIsChanged = TRUE; -USER_INPUT *gUserInput; -FORM_DISPLAY_ENGINE_FORM *gFormData; -EFI_HII_HANDLE gHiiHandle; -UINT16 gDirection; -LIST_ENTRY gMenuOption; -DISPLAY_HIGHLIGHT_MENU_INFO gHighligthMenuInfo = {0}; -BOOLEAN mIsFirstForm = TRUE; -FORM_ENTRY_INFO gOldFormEntry = {0}; - -// -// Browser Global Strings -// -CHAR16 *gFormNotFound; -CHAR16 *gNoSubmitIf; -CHAR16 *gBrwoserError; -CHAR16 *gSaveFailed; -CHAR16 *gPromptForData; -CHAR16 *gPromptForPassword; -CHAR16 *gPromptForNewPassword; -CHAR16 *gConfirmPassword; -CHAR16 *gConfirmError; -CHAR16 *gPassowordInvalid; -CHAR16 *gPressEnter; -CHAR16 *gEmptyString; -CHAR16 *gMiniString; -CHAR16 *gOptionMismatch; -CHAR16 *gFormSuppress; -CHAR16 *gProtocolNotFound; - -CHAR16 gPromptBlockWidth; -CHAR16 gOptionBlockWidth; -CHAR16 gHelpBlockWidth; -CHAR16 *mUnknownString; - -FORM_DISPLAY_DRIVER_PRIVATE_DATA mPrivateData = { - FORM_DISPLAY_DRIVER_SIGNATURE, - NULL, - { - FormDisplay, - DriverClearDisplayPage, - ConfirmDataChange - } -}; - - -/** - Get the string based on the StringId and HII Package List Handle. - - @param Token The String's ID. - @param HiiHandle The package list in the HII database to search for - the specified string. - - @return The output string. - -**/ -CHAR16 * -GetToken ( - IN EFI_STRING_ID Token, - IN EFI_HII_HANDLE HiiHandle - ) -{ - EFI_STRING String; - - String = HiiGetString (HiiHandle, Token, NULL); - if (String == NULL) { - String = AllocateCopyPool (StrSize (mUnknownString), mUnknownString); - ASSERT (String != NULL); - } - - return (CHAR16 *) String; -} - - -/** - Initialize the HII String Token to the correct values. - -**/ -VOID -InitializeDisplayStrings ( - VOID - ) -{ - mUnknownString = GetToken (STRING_TOKEN (UNKNOWN_STRING), gHiiHandle); - gSaveFailed = GetToken (STRING_TOKEN (SAVE_FAILED), gHiiHandle); - gPromptForData = GetToken (STRING_TOKEN (PROMPT_FOR_DATA), gHiiHandle); - gPromptForPassword = GetToken (STRING_TOKEN (PROMPT_FOR_PASSWORD), gHiiHandle); - gPromptForNewPassword = GetToken (STRING_TOKEN (PROMPT_FOR_NEW_PASSWORD), gHiiHandle); - gConfirmPassword = GetToken (STRING_TOKEN (CONFIRM_PASSWORD), gHiiHandle); - gConfirmError = GetToken (STRING_TOKEN (CONFIRM_ERROR), gHiiHandle); - gPassowordInvalid = GetToken (STRING_TOKEN (PASSWORD_INVALID), gHiiHandle); - gPressEnter = GetToken (STRING_TOKEN (PRESS_ENTER), gHiiHandle); - gEmptyString = GetToken (STRING_TOKEN (EMPTY_STRING), gHiiHandle); - gMiniString = GetToken (STRING_TOKEN (MINI_STRING), gHiiHandle); - gOptionMismatch = GetToken (STRING_TOKEN (OPTION_MISMATCH), gHiiHandle); - gFormSuppress = GetToken (STRING_TOKEN (FORM_SUPPRESSED), gHiiHandle); - gProtocolNotFound = GetToken (STRING_TOKEN (PROTOCOL_NOT_FOUND), gHiiHandle); - gFormNotFound = GetToken (STRING_TOKEN (STATUS_BROWSER_FORM_NOT_FOUND), gHiiHandle); - gNoSubmitIf = GetToken (STRING_TOKEN (STATUS_BROWSER_NO_SUBMIT_IF), gHiiHandle); - gBrwoserError = GetToken (STRING_TOKEN (STATUS_BROWSER_ERROR), gHiiHandle); -} - -/** - Free up the resource allocated for all strings required - by Setup Browser. - -**/ -VOID -FreeDisplayStrings ( - VOID - ) -{ - FreePool (mUnknownString); - FreePool (gEmptyString); - FreePool (gSaveFailed); - FreePool (gPromptForData); - FreePool (gPromptForPassword); - FreePool (gPromptForNewPassword); - FreePool (gConfirmPassword); - FreePool (gConfirmError); - FreePool (gPassowordInvalid); - FreePool (gPressEnter); - FreePool (gMiniString); - FreePool (gOptionMismatch); - FreePool (gFormSuppress); - FreePool (gProtocolNotFound); - FreePool (gBrwoserError); - FreePool (gNoSubmitIf); - FreePool (gFormNotFound); -} - -/** - Get prompt string id from the opcode data buffer. - - @param OpCode The input opcode buffer. - - @return The prompt string id. - -**/ -EFI_STRING_ID -GetPrompt ( - IN EFI_IFR_OP_HEADER *OpCode - ) -{ - EFI_IFR_STATEMENT_HEADER *Header; - - if (OpCode->Length <= sizeof (EFI_IFR_OP_HEADER)) { - return 0; - } - - Header = (EFI_IFR_STATEMENT_HEADER *) (OpCode + 1); - - return Header->Prompt; -} - -/** - Get the supported width for a particular op-code - - @param Statement The curent statement. - - @return Returns the number of CHAR16 characters that is support. - -**/ -UINT16 -GetWidth ( - IN FORM_DISPLAY_ENGINE_STATEMENT *Statement - ) -{ - CHAR16 *String; - UINTN Size; - UINT16 Width; - EFI_IFR_TEXT *TestOp; - - Size = 0; - - // - // See if the second text parameter is really NULL - // - if (Statement->OpCode->OpCode == EFI_IFR_TEXT_OP) { - TestOp = (EFI_IFR_TEXT *) Statement->OpCode; - if (TestOp->TextTwo != 0) { - String = GetToken (TestOp->TextTwo, gFormData->HiiHandle); - Size = StrLen (String); - FreePool (String); - } - } - - if ((Statement->OpCode->OpCode == EFI_IFR_SUBTITLE_OP) || - (Statement->OpCode->OpCode == EFI_IFR_REF_OP) || - (Statement->OpCode->OpCode == EFI_IFR_PASSWORD_OP) || - (Statement->OpCode->OpCode == EFI_IFR_ACTION_OP) || - (Statement->OpCode->OpCode == EFI_IFR_RESET_BUTTON_OP) || - // - // Allow a wide display if text op-code and no secondary text op-code - // - ((Statement->OpCode->OpCode == EFI_IFR_TEXT_OP) && (Size == 0)) - ) { - Width = (UINT16) (gPromptBlockWidth + gOptionBlockWidth); - } else { - Width = (UINT16) gPromptBlockWidth; - } - - return (UINT16) (Width - LEFT_SKIPPED_COLUMNS); -} - -/** - Will copy LineWidth amount of a string in the OutputString buffer and return the - number of CHAR16 characters that were copied into the OutputString buffer. - The output string format is: - Glyph Info + String info + '\0'. - - In the code, it deals \r,\n,\r\n same as \n\r, also it not process the \r or \g. - - @param InputString String description for this option. - @param LineWidth Width of the desired string to extract in CHAR16 - characters - @param GlyphWidth The glyph width of the begin of the char in the string. - @param Index Where in InputString to start the copy process - @param OutputString Buffer to copy the string into - - @return Returns the number of CHAR16 characters that were copied into the OutputString - buffer, include extra glyph info and '\0' info. - -**/ -UINT16 -GetLineByWidth ( - IN CHAR16 *InputString, - IN UINT16 LineWidth, - IN OUT UINT16 *GlyphWidth, - IN OUT UINTN *Index, - OUT CHAR16 **OutputString - ) -{ - UINT16 StrOffset; - UINT16 GlyphOffset; - UINT16 OriginalGlyphWidth; - BOOLEAN ReturnFlag; - UINT16 LastSpaceOffset; - UINT16 LastGlyphWidth; - - if (InputString == NULL || Index == NULL || OutputString == NULL) { - return 0; - } - - if (LineWidth == 0 || *GlyphWidth == 0) { - return 0; - } - - // - // Save original glyph width. - // - OriginalGlyphWidth = *GlyphWidth; - LastGlyphWidth = OriginalGlyphWidth; - ReturnFlag = FALSE; - LastSpaceOffset = 0; - - // - // 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. - // To avoid displaying this empty line in screen, just skip the two CHARs here. - // - if ((InputString[*Index] == NARROW_CHAR) && (InputString[*Index + 1] == CHAR_CARRIAGE_RETURN)) { - *Index = *Index + 2; - } - - // - // Fast-forward the string and see if there is a carriage-return in the string - // - for (StrOffset = 0, GlyphOffset = 0; GlyphOffset <= LineWidth; StrOffset++) { - switch (InputString[*Index + StrOffset]) { - case NARROW_CHAR: - *GlyphWidth = 1; - break; - - case WIDE_CHAR: - *GlyphWidth = 2; - break; - - case CHAR_CARRIAGE_RETURN: - case CHAR_LINEFEED: - case CHAR_NULL: - ReturnFlag = TRUE; - break; - - default: - GlyphOffset = GlyphOffset + *GlyphWidth; - - // - // Record the last space info in this line. Will be used in rewind. - // - if ((InputString[*Index + StrOffset] == CHAR_SPACE) && (GlyphOffset <= LineWidth)) { - LastSpaceOffset = StrOffset; - LastGlyphWidth = *GlyphWidth; - } - break; - } - - if (ReturnFlag) { - break; - } - } - - // - // Rewind the string from the maximum size until we see a space to break the line - // - if (GlyphOffset > LineWidth) { - // - // Rewind the string to last space char in this line. - // - if (LastSpaceOffset != 0) { - StrOffset = LastSpaceOffset; - *GlyphWidth = LastGlyphWidth; - } else { - // - // Roll back to last char in the line width. - // - StrOffset--; - } - } - - // - // The CHAR_NULL has process last time, this time just return 0 to stand for the end. - // - if (StrOffset == 0 && (InputString[*Index + StrOffset] == CHAR_NULL)) { - return 0; - } - - // - // Need extra glyph info and '\0' info, so +2. - // - *OutputString = AllocateZeroPool (((UINTN) (StrOffset + 2) * sizeof(CHAR16))); - if (*OutputString == NULL) { - return 0; - } - - // - // Save the glyph info at the begin of the string, will used by Print function. - // - if (OriginalGlyphWidth == 1) { - *(*OutputString) = NARROW_CHAR; - } else { - *(*OutputString) = WIDE_CHAR; - } - - CopyMem ((*OutputString) + 1, &InputString[*Index], StrOffset * sizeof(CHAR16)); - - if (InputString[*Index + StrOffset] == CHAR_SPACE) { - // - // Skip the space info at the begin of next line. - // - *Index = (UINT16) (*Index + StrOffset + 1); - } else if (InputString[*Index + StrOffset] == CHAR_LINEFEED) { - // - // Skip the /n or /n/r info. - // - if (InputString[*Index + StrOffset + 1] == CHAR_CARRIAGE_RETURN) { - *Index = (UINT16) (*Index + StrOffset + 2); - } else { - *Index = (UINT16) (*Index + StrOffset + 1); - } - } else if (InputString[*Index + StrOffset] == CHAR_CARRIAGE_RETURN) { - // - // Skip the /r or /r/n info. - // - if (InputString[*Index + StrOffset + 1] == CHAR_LINEFEED) { - *Index = (UINT16) (*Index + StrOffset + 2); - } else { - *Index = (UINT16) (*Index + StrOffset + 1); - } - } else { - *Index = (UINT16) (*Index + StrOffset); - } - - // - // Include extra glyph info and '\0' info, so +2. - // - return StrOffset + 2; -} - -/** - Add one menu option by specified description and context. - - @param Statement Statement of this Menu Option. - @param MenuItemCount The index for this Option in the Menu. - @param NestIn Whether this statement is nest in another statement. - -**/ -VOID -UiAddMenuOption ( - IN FORM_DISPLAY_ENGINE_STATEMENT *Statement, - IN UINT16 *MenuItemCount, - IN BOOLEAN NestIn - ) -{ - UI_MENU_OPTION *MenuOption; - UINTN Index; - UINTN Count; - CHAR16 *String; - UINT16 NumberOfLines; - UINT16 GlyphWidth; - UINT16 Width; - UINTN ArrayEntry; - CHAR16 *OutputString; - EFI_STRING_ID PromptId; - - NumberOfLines = 1; - ArrayEntry = 0; - GlyphWidth = 1; - Count = 1; - MenuOption = NULL; - - PromptId = GetPrompt (Statement->OpCode); - ASSERT (PromptId != 0); - - String = GetToken (PromptId, gFormData->HiiHandle); - ASSERT (String != NULL); - - Width = GetWidth (Statement); - for (; GetLineByWidth (String, Width, &GlyphWidth,&ArrayEntry, &OutputString) != 0x0000;) { - // - // If there is more string to process print on the next row and increment the Skip value - // - if (StrLen (&String[ArrayEntry]) != 0) { - NumberOfLines++; - } - FreePool (OutputString); - } - - if (Statement->OpCode->OpCode == EFI_IFR_DATE_OP || Statement->OpCode->OpCode == EFI_IFR_TIME_OP) { - // - // Add three MenuOptions for Date/Time - // Data format : [01/02/2004] [11:22:33] - // Line number : 0 0 1 0 0 1 - // - NumberOfLines = 0; - Count = 3; - } - - for (Index = 0; Index < Count; Index++) { - MenuOption = AllocateZeroPool (sizeof (UI_MENU_OPTION)); - ASSERT (MenuOption); - - MenuOption->Signature = UI_MENU_OPTION_SIGNATURE; - MenuOption->Description = String; - MenuOption->Handle = gFormData->HiiHandle; - MenuOption->ThisTag = Statement; - MenuOption->NestInStatement = NestIn; - MenuOption->EntryNumber = *MenuItemCount; - - if (Index == 2) { - // - // Override LineNumber for the MenuOption in Date/Time sequence - // - MenuOption->Skip = 1; - } else { - MenuOption->Skip = NumberOfLines; - } - MenuOption->Sequence = Index; - - if ((Statement->Attribute & HII_DISPLAY_GRAYOUT) != 0) { - MenuOption->GrayOut = TRUE; - } else { - MenuOption->GrayOut = FALSE; - } - - if ((Statement->Attribute & HII_DISPLAY_LOCK) != 0 || (gFormData->Attribute & HII_DISPLAY_LOCK) != 0) { - MenuOption->GrayOut = TRUE; - } - - // - // If the form or the question has the lock attribute, deal same as grayout. - // - if ((gFormData->Attribute & HII_DISPLAY_LOCK) != 0 || (Statement->Attribute & HII_DISPLAY_LOCK) != 0) { - MenuOption->GrayOut = TRUE; - } - - switch (Statement->OpCode->OpCode) { - case EFI_IFR_ORDERED_LIST_OP: - case EFI_IFR_ONE_OF_OP: - case EFI_IFR_NUMERIC_OP: - case EFI_IFR_TIME_OP: - case EFI_IFR_DATE_OP: - case EFI_IFR_CHECKBOX_OP: - case EFI_IFR_PASSWORD_OP: - case EFI_IFR_STRING_OP: - // - // User could change the value of these items - // - MenuOption->IsQuestion = TRUE; - break; - case EFI_IFR_TEXT_OP: - if (FeaturePcdGet (PcdBrowserGrayOutTextStatement)) { - // - // Initializing GrayOut option as TRUE for Text setup options - // so that those options will be Gray in colour and un selectable. - // - MenuOption->GrayOut = TRUE; - } - break; - default: - MenuOption->IsQuestion = FALSE; - break; - } - - if ((Statement->Attribute & HII_DISPLAY_READONLY) != 0) { - MenuOption->ReadOnly = TRUE; - if (FeaturePcdGet (PcdBrowerGrayOutReadOnlyMenu)) { - MenuOption->GrayOut = TRUE; - } - } - - InsertTailList (&gMenuOption, &MenuOption->Link); - } - - (*MenuItemCount)++; -} - -/** - Create the menu list base on the form data info. - -**/ -VOID -ConvertStatementToMenu ( - VOID - ) -{ - UINT16 MenuItemCount; - LIST_ENTRY *Link; - LIST_ENTRY *NestLink; - FORM_DISPLAY_ENGINE_STATEMENT *Statement; - FORM_DISPLAY_ENGINE_STATEMENT *NestStatement; - - MenuItemCount = 0; - InitializeListHead (&gMenuOption); - - Link = GetFirstNode (&gFormData->StatementListHead); - while (!IsNull (&gFormData->StatementListHead, Link)) { - Statement = FORM_DISPLAY_ENGINE_STATEMENT_FROM_LINK (Link); - Link = GetNextNode (&gFormData->StatementListHead, Link); - - // - // Skip the opcode not recognized by Display core. - // - if (Statement->OpCode->OpCode == EFI_IFR_GUID_OP) { - continue; - } - - UiAddMenuOption (Statement, &MenuItemCount, FALSE); - - // - // Check the statement nest in this host statement. - // - NestLink = GetFirstNode (&Statement->NestStatementList); - while (!IsNull (&Statement->NestStatementList, NestLink)) { - NestStatement = FORM_DISPLAY_ENGINE_STATEMENT_FROM_LINK (NestLink); - NestLink = GetNextNode (&Statement->NestStatementList, NestLink); - - UiAddMenuOption (NestStatement, &MenuItemCount, TRUE); - } - } -} - -/** - Count the storage space of a Unicode string. - - This function handles the Unicode string with NARROW_CHAR - and WIDE_CHAR control characters. NARROW_HCAR and WIDE_CHAR - does not count in the resultant output. If a WIDE_CHAR is - hit, then 2 Unicode character will consume an output storage - space with size of CHAR16 till a NARROW_CHAR is hit. - - If String is NULL, then ASSERT (). - - @param String The input string to be counted. - - @return Storage space for the input string. - -**/ -UINTN -GetStringWidth ( - IN CHAR16 *String - ) -{ - UINTN Index; - UINTN Count; - UINTN IncrementValue; - - ASSERT (String != NULL); - if (String == NULL) { - return 0; - } - - Index = 0; - Count = 0; - IncrementValue = 1; - - do { - // - // Advance to the null-terminator or to the first width directive - // - for (; - (String[Index] != NARROW_CHAR) && (String[Index] != WIDE_CHAR) && (String[Index] != 0); - Index++, Count = Count + IncrementValue - ) - ; - - // - // We hit the null-terminator, we now have a count - // - if (String[Index] == 0) { - break; - } - // - // We encountered a narrow directive - strip it from the size calculation since it doesn't get printed - // and also set the flag that determines what we increment by.(if narrow, increment by 1, if wide increment by 2) - // - if (String[Index] == NARROW_CHAR) { - // - // Skip to the next character - // - Index++; - IncrementValue = 1; - } else { - // - // Skip to the next character - // - Index++; - IncrementValue = 2; - } - } while (String[Index] != 0); - - // - // Increment by one to include the null-terminator in the size - // - Count++; - - return Count * sizeof (CHAR16); -} - -/** - Base on the input option string to update the skip value for a menu option. - - @param MenuOption The MenuOption to be checked. - @param OptionString The input option string. - -**/ -VOID -UpdateSkipInfoForMenu ( - IN UI_MENU_OPTION *MenuOption, - IN CHAR16 *OptionString - ) -{ - UINTN Index; - UINT16 Width; - UINTN Row; - CHAR16 *OutputString; - UINT16 GlyphWidth; - - Width = (UINT16) gOptionBlockWidth; - GlyphWidth = 1; - Row = 1; - - for (Index = 0; GetLineByWidth (OptionString, Width, &GlyphWidth, &Index, &OutputString) != 0x0000;) { - if (StrLen (&OptionString[Index]) != 0) { - Row++; - } - - FreePool (OutputString); - } - - if ((Row > MenuOption->Skip) && - (MenuOption->ThisTag->OpCode->OpCode != EFI_IFR_DATE_OP) && - (MenuOption->ThisTag->OpCode->OpCode != EFI_IFR_TIME_OP)) { - MenuOption->Skip = Row; - } -} - -/** - Update display lines for a Menu Option. - - @param MenuOption The MenuOption to be checked. - -**/ -VOID -UpdateOptionSkipLines ( - IN UI_MENU_OPTION *MenuOption - ) -{ - CHAR16 *OptionString; - - OptionString = NULL; - - ProcessOptions (MenuOption, FALSE, &OptionString, TRUE); - if (OptionString != NULL) { - UpdateSkipInfoForMenu (MenuOption, OptionString); - - FreePool (OptionString); - } - - if ((MenuOption->ThisTag->OpCode->OpCode == EFI_IFR_TEXT_OP) && (((EFI_IFR_TEXT*)MenuOption->ThisTag->OpCode)->TextTwo != 0)) { - OptionString = GetToken (((EFI_IFR_TEXT*)MenuOption->ThisTag->OpCode)->TextTwo, gFormData->HiiHandle); - - if (OptionString != NULL) { - UpdateSkipInfoForMenu (MenuOption, OptionString); - - FreePool (OptionString); - } - } -} - -/** - Check whether this Menu Option could be highlighted. - - This is an internal function. - - @param MenuOption The MenuOption to be checked. - - @retval TRUE This Menu Option is selectable. - @retval FALSE This Menu Option could not be selected. - -**/ -BOOLEAN -IsSelectable ( - UI_MENU_OPTION *MenuOption - ) -{ - if ((MenuOption->ThisTag->OpCode->OpCode == EFI_IFR_SUBTITLE_OP) || - MenuOption->GrayOut || MenuOption->ReadOnly) { - return FALSE; - } else { - return TRUE; - } -} - -/** - Move to next selectable statement. - - This is an internal function. - - @param GoUp The navigation direction. TRUE: up, FALSE: down. - @param CurrentPosition Current position. - @param GapToTop Gap position to top or bottom. - - @return The row distance from current MenuOption to next selectable MenuOption. - - @retval -1 Reach the begin of the menu, still can't find the selectable menu. - @retval Value Find the selectable menu, maybe the truly selectable, maybe the l - last menu showing at current form. - -**/ -INTN -MoveToNextStatement ( - IN BOOLEAN GoUp, - IN OUT LIST_ENTRY **CurrentPosition, - IN UINTN GapToTop - ) -{ - INTN Distance; - LIST_ENTRY *Pos; - UI_MENU_OPTION *NextMenuOption; - UI_MENU_OPTION *PreMenuOption; - - Distance = 0; - Pos = *CurrentPosition; - PreMenuOption = MENU_OPTION_FROM_LINK (Pos); - - while (TRUE) { - NextMenuOption = MENU_OPTION_FROM_LINK (Pos); - // - // NextMenuOption->Row == 0 means this menu has not calculate - // the NextMenuOption->Skip value yet, just calculate here. - // - if (NextMenuOption->Row == 0) { - UpdateOptionSkipLines (NextMenuOption); - } - - if (GoUp && (PreMenuOption != NextMenuOption)) { - // - // In this case, still can't find the selectable menu, - // return the last one in the showing form. - // - if ((UINTN) Distance + NextMenuOption->Skip > GapToTop) { - NextMenuOption = PreMenuOption; - break; - } - - // - // Current Position doesn't need to be caculated when go up. - // Caculate distanct at first when go up - // - Distance += NextMenuOption->Skip; - } - - if (IsSelectable (NextMenuOption)) { - break; - } - - // - // Arrive at begin of the menu list. - // - if ((GoUp ? Pos->BackLink : Pos->ForwardLink) == &gMenuOption) { - Distance = -1; - break; - } - - if (!GoUp) { - // - // In this case, still can't find the selectable menu, - // return the last one in the showing form. - // - if ((UINTN) Distance + NextMenuOption->Skip > GapToTop) { - NextMenuOption = PreMenuOption; - break; - } - - Distance += NextMenuOption->Skip; - } - - PreMenuOption = NextMenuOption; - Pos = (GoUp ? Pos->BackLink : Pos->ForwardLink); - } - - *CurrentPosition = &NextMenuOption->Link; - return Distance; -} - - -/** - Process option string for date/time opcode. - - @param MenuOption Menu option point to date/time. - @param OptionString Option string input for process. - @param AddOptCol Whether need to update MenuOption->OptCol. - -**/ -VOID -ProcessStringForDateTime ( - UI_MENU_OPTION *MenuOption, - CHAR16 *OptionString, - BOOLEAN AddOptCol - ) -{ - UINTN Index; - UINTN Count; - FORM_DISPLAY_ENGINE_STATEMENT *Statement; - EFI_IFR_DATE *Date; - EFI_IFR_TIME *Time; - - ASSERT (MenuOption != NULL && OptionString != NULL); - - Statement = MenuOption->ThisTag; - Date = NULL; - Time = NULL; - if (Statement->OpCode->OpCode == EFI_IFR_DATE_OP) { - Date = (EFI_IFR_DATE *) Statement->OpCode; - } else if (Statement->OpCode->OpCode == EFI_IFR_TIME_OP) { - Time = (EFI_IFR_TIME *) Statement->OpCode; - } - - // - // If leading spaces on OptionString - remove the spaces - // - for (Index = 0; OptionString[Index] == L' '; Index++) { - // - // Base on the blockspace to get the option column info. - // - if (AddOptCol) { - MenuOption->OptCol++; - } - } - - for (Count = 0; OptionString[Index] != CHAR_NULL; Index++) { - OptionString[Count] = OptionString[Index]; - Count++; - } - OptionString[Count] = CHAR_NULL; - - // - // Enable to suppress field in the opcode base on the flag. - // - if (Statement->OpCode->OpCode == EFI_IFR_DATE_OP) { - // - // OptionString format is: <**: **: ****> - // |month|day|year| - // 4 3 5 - // - if ((Date->Flags & EFI_QF_DATE_MONTH_SUPPRESS) && (MenuOption->Sequence == 0)) { - // - // At this point, only "<**:" in the optionstring. - // Clean the day's ** field, after clean, the format is "< :" - // - SetUnicodeMem (&OptionString[1], 2, L' '); - } else if ((Date->Flags & EFI_QF_DATE_DAY_SUPPRESS) && (MenuOption->Sequence == 1)) { - // - // At this point, only "**:" in the optionstring. - // Clean the month's "**" field, after clean, the format is " :" - // - SetUnicodeMem (&OptionString[0], 2, L' '); - } else if ((Date->Flags & EFI_QF_DATE_YEAR_SUPPRESS) && (MenuOption->Sequence == 2)) { - // - // At this point, only "****>" in the optionstring. - // Clean the year's "****" field, after clean, the format is " >" - // - SetUnicodeMem (&OptionString[0], 4, L' '); - } - } else if (Statement->OpCode->OpCode == EFI_IFR_TIME_OP) { - // - // OptionString format is: <**: **: **> - // |hour|minute|second| - // 4 3 3 - // - if ((Time->Flags & QF_TIME_HOUR_SUPPRESS) && (MenuOption->Sequence == 0)) { - // - // At this point, only "<**:" in the optionstring. - // Clean the hour's ** field, after clean, the format is "< :" - // - SetUnicodeMem (&OptionString[1], 2, L' '); - } else if ((Time->Flags & QF_TIME_MINUTE_SUPPRESS) && (MenuOption->Sequence == 1)) { - // - // At this point, only "**:" in the optionstring. - // Clean the minute's "**" field, after clean, the format is " :" - // - SetUnicodeMem (&OptionString[0], 2, L' '); - } else if ((Time->Flags & QF_TIME_SECOND_SUPPRESS) && (MenuOption->Sequence == 2)) { - // - // At this point, only "**>" in the optionstring. - // Clean the second's "**" field, after clean, the format is " >" - // - SetUnicodeMem (&OptionString[0], 2, L' '); - } - } -} - - -/** - Adjust Data and Time position accordingly. - Data format : [01/02/2004] [11:22:33] - Line number : 0 0 1 0 0 1 - - This is an internal function. - - @param DirectionUp the up or down direction. False is down. True is - up. - @param CurrentPosition Current position. On return: Point to the last - Option (Year or Second) if up; Point to the first - Option (Month or Hour) if down. - - @return Return line number to pad. It is possible that we stand on a zero-advance - @return data or time opcode, so pad one line when we judge if we are going to scroll outside. - -**/ -UINTN -AdjustDateAndTimePosition ( - IN BOOLEAN DirectionUp, - IN OUT LIST_ENTRY **CurrentPosition - ) -{ - UINTN Count; - LIST_ENTRY *NewPosition; - UI_MENU_OPTION *MenuOption; - UINTN PadLineNumber; - - PadLineNumber = 0; - NewPosition = *CurrentPosition; - MenuOption = MENU_OPTION_FROM_LINK (NewPosition); - - if ((MenuOption->ThisTag->OpCode->OpCode == EFI_IFR_DATE_OP) || - (MenuOption->ThisTag->OpCode->OpCode == EFI_IFR_TIME_OP)) { - // - // Calculate the distance from current position to the last Date/Time MenuOption - // - Count = 0; - while (MenuOption->Skip == 0) { - Count++; - NewPosition = NewPosition->ForwardLink; - MenuOption = MENU_OPTION_FROM_LINK (NewPosition); - PadLineNumber = 1; - } - - NewPosition = *CurrentPosition; - if (DirectionUp) { - // - // Since the behavior of hitting the up arrow on a Date/Time MenuOption is intended - // to be one that back to the previous set of MenuOptions, we need to advance to the first - // Date/Time MenuOption and leave the remaining logic in CfUiUp intact so the appropriate - // checking can be done. - // - while (Count++ < 2) { - NewPosition = NewPosition->BackLink; - } - } else { - // - // Since the behavior of hitting the down arrow on a Date/Time MenuOption is intended - // to be one that progresses to the next set of MenuOptions, we need to advance to the last - // Date/Time MenuOption and leave the remaining logic in CfUiDown intact so the appropriate - // checking can be done. - // - while (Count-- > 0) { - NewPosition = NewPosition->ForwardLink; - } - } - - *CurrentPosition = NewPosition; - } - - return PadLineNumber; -} - -/** - Get step info from numeric opcode. - - @param[in] OpCode The input numeric op code. - - @return step info for this opcode. -**/ -UINT64 -GetFieldFromNum ( - IN EFI_IFR_OP_HEADER *OpCode - ) -{ - EFI_IFR_NUMERIC *NumericOp; - UINT64 Step; - - NumericOp = (EFI_IFR_NUMERIC *) OpCode; - - switch (NumericOp->Flags & EFI_IFR_NUMERIC_SIZE) { - case EFI_IFR_NUMERIC_SIZE_1: - Step = NumericOp->data.u8.Step; - break; - - case EFI_IFR_NUMERIC_SIZE_2: - Step = NumericOp->data.u16.Step; - break; - - case EFI_IFR_NUMERIC_SIZE_4: - Step = NumericOp->data.u32.Step; - break; - - case EFI_IFR_NUMERIC_SIZE_8: - Step = NumericOp->data.u64.Step; - break; - - default: - Step = 0; - break; - } - - return Step; -} - -/** - Find the registered HotKey based on KeyData. - - @param[in] KeyData A pointer to a buffer that describes the keystroke - information for the hot key. - - @return The registered HotKey context. If no found, NULL will return. -**/ -BROWSER_HOT_KEY * -GetHotKeyFromRegisterList ( - IN EFI_INPUT_KEY *KeyData - ) -{ - LIST_ENTRY *Link; - BROWSER_HOT_KEY *HotKey; - - Link = GetFirstNode (&gFormData->HotKeyListHead); - while (!IsNull (&gFormData->HotKeyListHead, Link)) { - HotKey = BROWSER_HOT_KEY_FROM_LINK (Link); - - if (HotKey->KeyData->ScanCode == KeyData->ScanCode) { - return HotKey; - } - - Link = GetNextNode (&gFormData->HotKeyListHead, Link); - } - - return NULL; -} - - -/** - Determine if the menu is the last menu that can be selected. - - This is an internal function. - - @param Direction The scroll direction. False is down. True is up. - @param CurrentPos The current focus. - - @return FALSE -- the menu isn't the last menu that can be selected. - @return TRUE -- the menu is the last menu that can be selected. - -**/ -BOOLEAN -ValueIsScroll ( - IN BOOLEAN Direction, - IN LIST_ENTRY *CurrentPos - ) -{ - LIST_ENTRY *Temp; - - Temp = Direction ? CurrentPos->BackLink : CurrentPos->ForwardLink; - - if (Temp == &gMenuOption) { - return TRUE; - } - - return FALSE; -} - -/** - Wait for a given event to fire, or for an optional timeout to expire. - - @param Event The event to wait for - - @retval UI_EVENT_TYPE The type of the event which is trigged. - -**/ -UI_EVENT_TYPE -UiWaitForEvent ( - IN EFI_EVENT Event - ) -{ - EFI_STATUS Status; - UINTN Index; - UINTN EventNum; - UINT64 Timeout; - EFI_EVENT TimerEvent; - EFI_EVENT WaitList[3]; - UI_EVENT_TYPE EventType; - - TimerEvent = NULL; - Timeout = FormExitTimeout(gFormData); - - if (Timeout != 0) { - Status = gBS->CreateEvent (EVT_TIMER, 0, NULL, NULL, &TimerEvent); - - // - // Set the timer event - // - gBS->SetTimer ( - TimerEvent, - TimerRelative, - Timeout - ); - } - - WaitList[0] = Event; - EventNum = 1; - if (gFormData->FormRefreshEvent != NULL) { - WaitList[EventNum] = gFormData->FormRefreshEvent; - EventNum ++; - } - - if (Timeout != 0) { - WaitList[EventNum] = TimerEvent; - EventNum ++; - } - - Status = gBS->WaitForEvent (EventNum, WaitList, &Index); - ASSERT_EFI_ERROR (Status); - - switch (Index) { - case 0: - EventType = UIEventKey; - break; - - case 1: - if (gFormData->FormRefreshEvent != NULL) { - EventType = UIEventDriver; - } else { - ASSERT (Timeout != 0 && EventNum == 2); - EventType = UIEventTimeOut; - } - break; - - default: - ASSERT (Index == 2 && EventNum == 3); - EventType = UIEventTimeOut; - break; - } - - if (Timeout != 0) { - gBS->CloseEvent (TimerEvent); - } - - return EventType; -} - -/** - Get question id info from the input opcode header. - - @param OpCode The input opcode header pointer. - - @retval The question id for this opcode. - -**/ -EFI_QUESTION_ID -GetQuestionIdInfo ( - IN EFI_IFR_OP_HEADER *OpCode - ) -{ - EFI_IFR_QUESTION_HEADER *QuestionHeader; - - if (OpCode->Length < sizeof (EFI_IFR_OP_HEADER) + sizeof (EFI_IFR_QUESTION_HEADER)) { - return 0; - } - - QuestionHeader = (EFI_IFR_QUESTION_HEADER *)((UINT8 *) OpCode + sizeof(EFI_IFR_OP_HEADER)); - - return QuestionHeader->QuestionId; -} - -/** - Find the first menu which will be show at the top. - - @param FormData The data info for this form. - @param TopOfScreen The link_entry pointer to top menu. - @param HighlightMenu The menu which will be highlight. - @param SkipValue The skip value for the top menu. - -**/ -VOID -FindTopMenu ( - IN FORM_DISPLAY_ENGINE_FORM *FormData, - OUT LIST_ENTRY **TopOfScreen, - OUT LIST_ENTRY **HighlightMenu, - OUT INTN *SkipValue - ) -{ - LIST_ENTRY *Link; - LIST_ENTRY *NewPos; - UINTN TopRow; - UINTN BottomRow; - UINTN Index; - UI_MENU_OPTION *SavedMenuOption; - UINTN EndRow; - - TopRow = gStatementDimensions.TopRow + SCROLL_ARROW_HEIGHT; - BottomRow = gStatementDimensions.BottomRow - SCROLL_ARROW_HEIGHT; - - // - // If not has input highlight statement, just return the first one in this form. - // - if (FormData->HighLightedStatement == NULL) { - *TopOfScreen = gMenuOption.ForwardLink; - *HighlightMenu = gMenuOption.ForwardLink; - if (!IsListEmpty (&gMenuOption)) { - MoveToNextStatement (FALSE, HighlightMenu, BottomRow - TopRow); - } - *SkipValue = 0; - return; - } - - // - // Now base on the input highlight menu to find the top menu in this page. - // Will base on the highlight menu show at the bottom to find the top menu. - // - NewPos = gMenuOption.ForwardLink; - SavedMenuOption = MENU_OPTION_FROM_LINK (NewPos); - - while ((SavedMenuOption->ThisTag != FormData->HighLightedStatement) || - (SavedMenuOption->Sequence != gSequence)) { - NewPos = NewPos->ForwardLink; - if (NewPos == &gMenuOption) { - // - // Not Found it, break - // - break; - } - SavedMenuOption = MENU_OPTION_FROM_LINK (NewPos); - } - ASSERT (SavedMenuOption->ThisTag == FormData->HighLightedStatement); - - *HighlightMenu = NewPos; - - AdjustDateAndTimePosition(FALSE, &NewPos); - SavedMenuOption = MENU_OPTION_FROM_LINK (NewPos); - UpdateOptionSkipLines (SavedMenuOption); - - // - // If highlight opcode is date/time, keep the highlight row info not change. - // - if ((SavedMenuOption->ThisTag->OpCode->OpCode == EFI_IFR_DATE_OP || SavedMenuOption->ThisTag->OpCode->OpCode == EFI_IFR_TIME_OP) && - (gHighligthMenuInfo.QuestionId != 0) && - (gHighligthMenuInfo.QuestionId == GetQuestionIdInfo(SavedMenuOption->ThisTag->OpCode))) { - // - // Still show the highlight menu before exit from display engine. - // - EndRow = gHighligthMenuInfo.DisplayRow + SavedMenuOption->Skip; - } else { - EndRow = BottomRow; - } - - // - // Base on the selected menu will show at the bottome of next page, - // select the menu show at the top of the next page. - // - Link = NewPos; - for (Index = TopRow + SavedMenuOption->Skip; Index <= EndRow; ) { - Link = Link->BackLink; - // - // Already find the first menu in this form, means highlight menu - // will show in first page of this form. - // - if (Link == &gMenuOption) { - *TopOfScreen = gMenuOption.ForwardLink; - *SkipValue = 0; - return; - } - SavedMenuOption = MENU_OPTION_FROM_LINK (Link); - UpdateOptionSkipLines (SavedMenuOption); - Index += SavedMenuOption->Skip; - } - - // - // Found the menu which will show at the top of the page. - // - if (Link == NewPos) { - // - // The menu can show more than one pages, just show the menu at the top of the page. - // - *SkipValue = 0; - *TopOfScreen = Link; - } else { - // - // Check whether need to skip some line for menu shows at the top of the page. - // - *SkipValue = Index - EndRow; - if (*SkipValue > 0 && *SkipValue < (INTN) SavedMenuOption->Skip) { - *TopOfScreen = Link; - } else { - *SkipValue = 0; - *TopOfScreen = Link->ForwardLink; - } - } -} - -/** - Display menu and wait for user to select one menu option, then return it. - If AutoBoot is enabled, then if user doesn't select any option, - after period of time, it will automatically return the first menu option. - - @param FormData The current form data info. - - @retval EFI_SUCESSS Process the user selection success. - @retval EFI_NOT_FOUND Process option string for orderedlist/Oneof fail. - -**/ -EFI_STATUS -UiDisplayMenu ( - IN FORM_DISPLAY_ENGINE_FORM *FormData - ) -{ - INTN SkipValue; - INTN Difference; - UINTN DistanceValue; - UINTN Row; - UINTN Col; - UINTN TempRightCol; - UINTN Temp; - UINTN Temp2; - UINTN Temp3; - UINTN TopRow; - UINTN BottomRow; - UINTN OriginalRow; - UINTN Index; - UINT16 Width; - CHAR16 *StringPtr; - CHAR16 *OptionString; - CHAR16 *OutputString; - CHAR16 *HelpString; - CHAR16 *HelpHeaderString; - CHAR16 *HelpBottomString; - BOOLEAN NewLine; - BOOLEAN Repaint; - BOOLEAN UpArrow; - BOOLEAN DownArrow; - EFI_STATUS Status; - EFI_INPUT_KEY Key; - LIST_ENTRY *Link; - LIST_ENTRY *NewPos; - LIST_ENTRY *TopOfScreen; - LIST_ENTRY *SavedListEntry; - UI_MENU_OPTION *MenuOption; - UI_MENU_OPTION *NextMenuOption; - UI_MENU_OPTION *SavedMenuOption; - UI_MENU_OPTION *PreviousMenuOption; - UI_CONTROL_FLAG ControlFlag; - UI_SCREEN_OPERATION ScreenOperation; - UINT16 DefaultId; - FORM_DISPLAY_ENGINE_STATEMENT *Statement; - UINTN ModalSkipColumn; - BROWSER_HOT_KEY *HotKey; - UINTN HelpPageIndex; - UINTN HelpPageCount; - UINTN RowCount; - UINTN HelpLine; - UINTN HelpHeaderLine; - UINTN HelpBottomLine; - BOOLEAN MultiHelpPage; - UINT16 GlyphWidth; - UINT16 EachLineWidth; - UINT16 HeaderLineWidth; - UINT16 BottomLineWidth; - EFI_STRING_ID HelpInfo; - UI_EVENT_TYPE EventType; - FORM_DISPLAY_ENGINE_STATEMENT *InitialHighlight; - - EventType = UIEventNone; - Status = EFI_SUCCESS; - HelpString = NULL; - HelpHeaderString = NULL; - HelpBottomString = NULL; - OptionString = NULL; - ScreenOperation = UiNoOperation; - NewLine = TRUE; - DefaultId = 0; - HelpPageCount = 0; - HelpLine = 0; - RowCount = 0; - HelpBottomLine = 0; - HelpHeaderLine = 0; - HelpPageIndex = 0; - MultiHelpPage = FALSE; - EachLineWidth = 0; - HeaderLineWidth = 0; - BottomLineWidth = 0; - OutputString = NULL; - UpArrow = FALSE; - DownArrow = FALSE; - SkipValue = 0; - - NextMenuOption = NULL; - PreviousMenuOption = NULL; - SavedMenuOption = NULL; - HotKey = NULL; - Repaint = TRUE; - MenuOption = NULL; - ModalSkipColumn = (gStatementDimensions.RightColumn - gStatementDimensions.LeftColumn) / 6; - InitialHighlight = gFormData->HighLightedStatement; - - ZeroMem (&Key, sizeof (EFI_INPUT_KEY)); - - gOptionBlockWidth = (CHAR16) ((gStatementDimensions.RightColumn - gStatementDimensions.LeftColumn) / 3); - gPromptBlockWidth = (CHAR16) (gOptionBlockWidth + LEFT_SKIPPED_COLUMNS); - gHelpBlockWidth = (CHAR16) (gOptionBlockWidth - LEFT_SKIPPED_COLUMNS); - - TopRow = gStatementDimensions.TopRow + SCROLL_ARROW_HEIGHT; - BottomRow = gStatementDimensions.BottomRow - SCROLL_ARROW_HEIGHT - 1; - - Row = TopRow; - if ((FormData->Attribute & HII_DISPLAY_MODAL) != 0) { - Col = gStatementDimensions.LeftColumn + LEFT_SKIPPED_COLUMNS + ModalSkipColumn; - } else { - Col = gStatementDimensions.LeftColumn + LEFT_SKIPPED_COLUMNS; - } - - FindTopMenu(FormData, &TopOfScreen, &NewPos, &SkipValue); - - gST->ConOut->EnableCursor (gST->ConOut, FALSE); - - ControlFlag = CfInitialization; - while (TRUE) { - switch (ControlFlag) { - case CfInitialization: - if (IsListEmpty (&gMenuOption)) { - - if ((FormData->Attribute & HII_DISPLAY_MODAL) == 0) { - // - // Clear Statement range. - // - ClearLines ( - gStatementDimensions.LeftColumn, - gStatementDimensions.RightColumn, - TopRow - SCROLL_ARROW_HEIGHT, - BottomRow + SCROLL_ARROW_HEIGHT, - GetFieldTextColor () - ); - - // - // Clear Key Range - // - RefreshKeyHelp (gFormData, NULL, FALSE); - } - - ControlFlag = CfReadKey; - } else { - ControlFlag = CfRepaint; - } - break; - - case CfRepaint: - ControlFlag = CfRefreshHighLight; - - if (Repaint) { - // - // Display menu - // - DownArrow = FALSE; - UpArrow = FALSE; - Row = TopRow; - - Temp = (UINTN) SkipValue; - Temp2 = (UINTN) SkipValue; - Temp3 = (UINTN) SkipValue; - - // - // 1. Clear the screen. - // - if ((FormData->Attribute & HII_DISPLAY_MODAL) != 0) { - ClearLines ( - gStatementDimensions.LeftColumn + ModalSkipColumn, - gStatementDimensions.LeftColumn + ModalSkipColumn + gPromptBlockWidth + gOptionBlockWidth, - TopRow - SCROLL_ARROW_HEIGHT, - BottomRow + SCROLL_ARROW_HEIGHT, - GetFieldTextColor () - ); - } else { - TempRightCol = gStatementDimensions.RightColumn; - if (!mStatementLayoutIsChanged) { - TempRightCol = gStatementDimensions.RightColumn - gHelpBlockWidth; - } - ClearLines ( - gStatementDimensions.LeftColumn, - gStatementDimensions.RightColumn, - TopRow - SCROLL_ARROW_HEIGHT, - TopRow - 1, - GetFieldTextColor () - ); - ClearLines ( - gStatementDimensions.LeftColumn, - TempRightCol, - TopRow, - BottomRow, - GetFieldTextColor () - ); - ClearLines ( - gStatementDimensions.LeftColumn, - gStatementDimensions.RightColumn, - BottomRow + 1, - BottomRow + SCROLL_ARROW_HEIGHT, - GetFieldTextColor () - ); - } - - // - // 2.Paint the menu. - // - for (Link = TopOfScreen; Link != &gMenuOption; Link = Link->ForwardLink) { - MenuOption = MENU_OPTION_FROM_LINK (Link); - MenuOption->Row = Row; - MenuOption->Col = Col; - if ((FormData->Attribute & HII_DISPLAY_MODAL) != 0) { - MenuOption->OptCol = gPromptBlockWidth + 1 + gStatementDimensions.LeftColumn + ModalSkipColumn; - } else { - MenuOption->OptCol = gPromptBlockWidth + 1 + gStatementDimensions.LeftColumn; - } - - Statement = MenuOption->ThisTag; - if (MenuOption->NestInStatement) { - MenuOption->Col += SUBTITLE_INDENT; - } - - if (MenuOption->GrayOut) { - gST->ConOut->SetAttribute (gST->ConOut, GetGrayedTextColor ()); - } else { - if (Statement->OpCode->OpCode == EFI_IFR_SUBTITLE_OP) { - gST->ConOut->SetAttribute (gST->ConOut, GetSubTitleTextColor ()); - } - } - - Width = GetWidth (Statement); - OriginalRow = Row; - GlyphWidth = 1; - - if (Statement->OpCode->OpCode == EFI_IFR_REF_OP && MenuOption->Col >= 2) { - // - // Print Arrow for Goto button. - // - PrintCharAt ( - MenuOption->Col - 2, - Row, - GEOMETRICSHAPE_RIGHT_TRIANGLE - ); - } - - // - // 2.1. Paint the description. - // - for (Index = 0; GetLineByWidth (MenuOption->Description, Width, &GlyphWidth, &Index, &OutputString) != 0x0000;) { - // - // Temp means need to skip how many lines from the start. - // - if ((Temp == 0) && (Row <= BottomRow)) { - PrintStringAt (MenuOption->Col, Row, OutputString); - } - // - // If there is more string to process print on the next row and increment the Skip value - // - if (StrLen (&MenuOption->Description[Index]) != 0) { - if (Temp == 0) { - Row++; - } - } - - FreePool (OutputString); - if (Temp != 0) { - Temp--; - } - } - - Temp = 0; - Row = OriginalRow; - - // - // 2.2. Paint the option string. - // - Status = ProcessOptions (MenuOption, FALSE, &OptionString, FALSE); - // - // If Error occur, question value update in ProcessOptions. - // Exit current FormDisplay with new question value. - // - if (EFI_ERROR (Status)) { - return Status; - } - - if (OptionString != NULL) { - if (Statement->OpCode->OpCode == EFI_IFR_DATE_OP || Statement->OpCode->OpCode == EFI_IFR_TIME_OP) { - ProcessStringForDateTime(MenuOption, OptionString, TRUE); - } - - Width = (UINT16) gOptionBlockWidth; - OriginalRow = Row; - GlyphWidth = 1; - - for (Index = 0; GetLineByWidth (OptionString, Width, &GlyphWidth, &Index, &OutputString) != 0x0000;) { - if ((Temp2 == 0) && (Row <= BottomRow)) { - PrintStringAt (MenuOption->OptCol, Row, OutputString); - } - // - // If there is more string to process print on the next row and increment the Skip value - // - if (StrLen (&OptionString[Index]) != 0) { - if (Temp2 == 0) { - Row++; - // - // Since the Number of lines for this menu entry may or may not be reflected accurately - // since the prompt might be 1 lines and option might be many, and vice versa, we need to do - // some testing to ensure we are keeping this in-sync. - // - // If the difference in rows is greater than or equal to the skip value, increase the skip value - // - if ((Row - OriginalRow) >= MenuOption->Skip) { - MenuOption->Skip++; - } - } - } - - FreePool (OutputString); - if (Temp2 != 0) { - Temp2--; - } - } - - Row = OriginalRow; - - FreePool (OptionString); - } - Temp2 = 0; - - // - // If this is a text op with secondary text information - // - if ((Statement->OpCode->OpCode == EFI_IFR_TEXT_OP) && (((EFI_IFR_TEXT*)Statement->OpCode)->TextTwo != 0)) { - StringPtr = GetToken (((EFI_IFR_TEXT*)Statement->OpCode)->TextTwo, gFormData->HiiHandle); - - Width = (UINT16) gOptionBlockWidth; - OriginalRow = Row; - GlyphWidth = 1; - - for (Index = 0; GetLineByWidth (StringPtr, Width, &GlyphWidth, &Index, &OutputString) != 0x0000;) { - if ((Temp3 == 0) && (Row <= BottomRow)) { - PrintStringAt (MenuOption->OptCol, Row, OutputString); - } - // - // If there is more string to process print on the next row and increment the Skip value - // - if (StrLen (&StringPtr[Index]) != 0) { - if (Temp3 == 0) { - Row++; - // - // Since the Number of lines for this menu entry may or may not be reflected accurately - // since the prompt might be 1 lines and option might be many, and vice versa, we need to do - // some testing to ensure we are keeping this in-sync. - // - // If the difference in rows is greater than or equal to the skip value, increase the skip value - // - if ((Row - OriginalRow) >= MenuOption->Skip) { - MenuOption->Skip++; - } - } - } - - FreePool (OutputString); - if (Temp3 != 0) { - Temp3--; - } - } - - Row = OriginalRow; - FreePool (StringPtr); - } - Temp3 = 0; - - gST->ConOut->SetAttribute (gST->ConOut, GetFieldTextColor ()); - - // - // 3. Update the row info which will be used by next menu. - // - if (Link == TopOfScreen) { - Row += MenuOption->Skip - SkipValue; - } else { - Row += MenuOption->Skip; - } - - if (Row > BottomRow) { - if (!ValueIsScroll (FALSE, Link)) { - DownArrow = TRUE; - } - - Row = BottomRow + 1; - break; - } - } - - if (!ValueIsScroll (TRUE, TopOfScreen)) { - UpArrow = TRUE; - } - - if (UpArrow) { - gST->ConOut->SetAttribute (gST->ConOut, GetArrowColor ()); - PrintCharAt ( - gStatementDimensions.LeftColumn + gPromptBlockWidth + gOptionBlockWidth + 1, - TopRow - SCROLL_ARROW_HEIGHT, - ARROW_UP - ); - gST->ConOut->SetAttribute (gST->ConOut, GetFieldTextColor ()); - } - - if (DownArrow) { - gST->ConOut->SetAttribute (gST->ConOut, GetArrowColor ()); - PrintCharAt ( - gStatementDimensions.LeftColumn + gPromptBlockWidth + gOptionBlockWidth + 1, - BottomRow + SCROLL_ARROW_HEIGHT, - ARROW_DOWN - ); - gST->ConOut->SetAttribute (gST->ConOut, GetFieldTextColor ()); - } - - MenuOption = NULL; - } - break; - - case CfRefreshHighLight: - - // - // MenuOption: Last menu option that need to remove hilight - // MenuOption is set to NULL in Repaint - // NewPos: Current menu option that need to hilight - // - ControlFlag = CfUpdateHelpString; - - if (MenuOption != NULL && TopOfScreen == &MenuOption->Link) { - Temp = SkipValue; - } else { - Temp = 0; - } - if (NewPos == TopOfScreen) { - Temp2 = SkipValue; - } else { - Temp2 = 0; - } - - if (NewPos != NULL && (MenuOption == NULL || NewPos != &MenuOption->Link)) { - if (MenuOption != NULL) { - // - // Remove highlight on last Menu Option - // - gST->ConOut->SetCursorPosition (gST->ConOut, MenuOption->Col, MenuOption->Row); - ProcessOptions (MenuOption, FALSE, &OptionString, TRUE); - gST->ConOut->SetAttribute (gST->ConOut, GetFieldTextColor ()); - if (OptionString != NULL) { - if ((MenuOption->ThisTag->OpCode->OpCode == EFI_IFR_DATE_OP) || - (MenuOption->ThisTag->OpCode->OpCode == EFI_IFR_TIME_OP) - ) { - ProcessStringForDateTime(MenuOption, OptionString, FALSE); - } - - Width = (UINT16) gOptionBlockWidth; - OriginalRow = MenuOption->Row; - GlyphWidth = 1; - - for (Index = 0; GetLineByWidth (OptionString, Width, &GlyphWidth, &Index, &OutputString) != 0x0000;) { - if ((Temp == 0) && (MenuOption->Row >= TopRow) && (MenuOption->Row <= BottomRow)) { - PrintStringAt (MenuOption->OptCol, MenuOption->Row, OutputString); - } - // - // If there is more string to process print on the next row and increment the Skip value - // - if (StrLen (&OptionString[Index]) != 0) { - if (Temp == 0) { - MenuOption->Row++; - } - } - - FreePool (OutputString); - if (Temp != 0) { - Temp--; - } - } - - MenuOption->Row = OriginalRow; - - FreePool (OptionString); - } else { - if (NewLine) { - if (MenuOption->GrayOut) { - gST->ConOut->SetAttribute (gST->ConOut, GetGrayedTextColor ()); - } else if (MenuOption->ThisTag->OpCode->OpCode == EFI_IFR_SUBTITLE_OP) { - gST->ConOut->SetAttribute (gST->ConOut, GetSubTitleTextColor ()); - } - - OriginalRow = MenuOption->Row; - Width = GetWidth (MenuOption->ThisTag); - GlyphWidth = 1; - - for (Index = 0; GetLineByWidth (MenuOption->Description, Width, &GlyphWidth, &Index, &OutputString) != 0x0000;) { - if ((Temp == 0) && (MenuOption->Row >= TopRow) && (MenuOption->Row <= BottomRow)) { - PrintStringAt (MenuOption->Col, MenuOption->Row, OutputString); - } - // - // If there is more string to process print on the next row and increment the Skip value - // - if (StrLen (&MenuOption->Description[Index]) != 0) { - if (Temp == 0) { - MenuOption->Row++; - } - } - - FreePool (OutputString); - if (Temp != 0) { - Temp--; - } - } - - MenuOption->Row = OriginalRow; - gST->ConOut->SetAttribute (gST->ConOut, GetFieldTextColor ()); - } - } - } - - // - // This is the current selected statement - // - MenuOption = MENU_OPTION_FROM_LINK (NewPos); - Statement = MenuOption->ThisTag; - - // - // Get the highlight statement. - // - gUserInput->SelectedStatement = Statement; - gSequence = (UINT16) MenuOption->Sequence; - - // - // Record highlight row info for date/time opcode. - // - if (Statement->OpCode->OpCode == EFI_IFR_DATE_OP || Statement->OpCode->OpCode == EFI_IFR_TIME_OP) { - gHighligthMenuInfo.QuestionId = GetQuestionIdInfo(Statement->OpCode); - gHighligthMenuInfo.DisplayRow = (UINT16) MenuOption->Row; - } else { - gHighligthMenuInfo.QuestionId = 0; - gHighligthMenuInfo.DisplayRow = 0; - } - - if (!IsSelectable (MenuOption)) { - RefreshKeyHelp(gFormData, Statement, FALSE); - break; - } - - // - // Set reverse attribute - // - gST->ConOut->SetAttribute (gST->ConOut, GetHighlightTextColor ()); - gST->ConOut->SetCursorPosition (gST->ConOut, MenuOption->Col, MenuOption->Row); - - ProcessOptions (MenuOption, FALSE, &OptionString, TRUE); - if (OptionString != NULL) { - if (Statement->OpCode->OpCode == EFI_IFR_DATE_OP || Statement->OpCode->OpCode == EFI_IFR_TIME_OP) { - ProcessStringForDateTime(MenuOption, OptionString, FALSE); - } - Width = (UINT16) gOptionBlockWidth; - - OriginalRow = MenuOption->Row; - GlyphWidth = 1; - - for (Index = 0; GetLineByWidth (OptionString, Width, &GlyphWidth, &Index, &OutputString) != 0x0000;) { - if ((Temp2 == 0) && (MenuOption->Row >= TopRow) && (MenuOption->Row <= BottomRow) ) { - PrintStringAt (MenuOption->OptCol, MenuOption->Row, OutputString); - } - // - // If there is more string to process print on the next row and increment the Skip value - // - if (StrLen (&OptionString[Index]) != 0) { - if (Temp2 == 0) { - MenuOption->Row++; - } - } - - FreePool (OutputString); - if (Temp2 != 0) { - Temp2--; - } - } - - MenuOption->Row = OriginalRow; - - FreePool (OptionString); - } else { - if (NewLine) { - OriginalRow = MenuOption->Row; - - Width = GetWidth (Statement); - GlyphWidth = 1; - - for (Index = 0; GetLineByWidth (MenuOption->Description, Width, &GlyphWidth, &Index, &OutputString) != 0x0000;) { - if ((Temp2 == 0) && (MenuOption->Row >= TopRow) && (MenuOption->Row <= BottomRow) ) { - PrintStringAt (MenuOption->Col, MenuOption->Row, OutputString); - } - // - // If there is more string to process print on the next row and increment the Skip value - // - if (StrLen (&MenuOption->Description[Index]) != 0) { - if (Temp2 == 0) { - MenuOption->Row++; - } - } - - FreePool (OutputString); - if (Temp2 != 0) { - Temp2--; - } - } - - MenuOption->Row = OriginalRow; - - } - } - - RefreshKeyHelp(gFormData, MenuOption->ThisTag, FALSE); - - // - // Clear reverse attribute - // - gST->ConOut->SetAttribute (gST->ConOut, GetFieldTextColor ()); - } - break; - - case CfUpdateHelpString: - ControlFlag = CfPrepareToReadKey; - if ((FormData->Attribute & HII_DISPLAY_MODAL) != 0) { - break; - } - - if (Repaint || NewLine) { - // - // Don't print anything if it is a NULL help token - // - ASSERT(MenuOption != NULL); - HelpInfo = ((EFI_IFR_STATEMENT_HEADER *) ((CHAR8 *)MenuOption->ThisTag->OpCode + sizeof (EFI_IFR_OP_HEADER)))->Help; - if (HelpInfo == 0 || !IsSelectable (MenuOption)) { - StringPtr = GetToken (STRING_TOKEN (EMPTY_STRING), gHiiHandle); - } else { - StringPtr = GetToken (HelpInfo, gFormData->HiiHandle); - } - - RowCount = BottomRow - TopRow + 1; - HelpPageIndex = 0; - // - // 1.Calculate how many line the help string need to print. - // - if (HelpString != NULL) { - FreePool (HelpString); - HelpString = NULL; - } - HelpLine = ProcessHelpString (StringPtr, &HelpString, &EachLineWidth, RowCount); - FreePool (StringPtr); - - if (HelpLine > RowCount) { - MultiHelpPage = TRUE; - StringPtr = GetToken (STRING_TOKEN(ADJUST_HELP_PAGE_UP), gHiiHandle); - if (HelpHeaderString != NULL) { - FreePool (HelpHeaderString); - HelpHeaderString = NULL; - } - HelpHeaderLine = ProcessHelpString (StringPtr, &HelpHeaderString, &HeaderLineWidth, 0); - FreePool (StringPtr); - StringPtr = GetToken (STRING_TOKEN(ADJUST_HELP_PAGE_DOWN), gHiiHandle); - if (HelpBottomString != NULL) { - FreePool (HelpBottomString); - HelpBottomString = NULL; - } - HelpBottomLine = ProcessHelpString (StringPtr, &HelpBottomString, &BottomLineWidth, 0); - FreePool (StringPtr); - // - // Calculate the help page count. - // - if (HelpLine > 2 * RowCount - 2) { - HelpPageCount = (HelpLine - RowCount + 1) / (RowCount - 2) + 1; - if ((HelpLine - RowCount + 1) % (RowCount - 2) > 1) { - HelpPageCount += 1; - } - } else { - HelpPageCount = 2; - } - } else { - MultiHelpPage = FALSE; - } - } - - // - // Check whether need to show the 'More(U/u)' at the begin. - // Base on current direct info, here shows aligned to the right side of the column. - // If the direction is multi line and aligned to right side may have problem, so - // add ASSERT code here. - // - if (HelpPageIndex > 0) { - gST->ConOut->SetAttribute (gST->ConOut, GetInfoTextColor ()); - for (Index = 0; Index < HelpHeaderLine; Index++) { - ASSERT (HelpHeaderLine == 1); - ASSERT (GetStringWidth (HelpHeaderString) / 2 < (UINTN) (gHelpBlockWidth - 1)); - PrintStringAtWithWidth ( - gStatementDimensions.RightColumn - gHelpBlockWidth, - Index + TopRow, - gEmptyString, - gHelpBlockWidth - ); - PrintStringAt ( - gStatementDimensions.RightColumn - GetStringWidth (HelpHeaderString) / 2 - 1, - Index + TopRow, - &HelpHeaderString[Index * HeaderLineWidth] - ); - } - } - - gST->ConOut->SetAttribute (gST->ConOut, GetHelpTextColor ()); - // - // Print the help string info. - // - if (!MultiHelpPage) { - for (Index = 0; Index < HelpLine; Index++) { - PrintStringAtWithWidth ( - gStatementDimensions.RightColumn - gHelpBlockWidth, - Index + TopRow, - &HelpString[Index * EachLineWidth], - gHelpBlockWidth - ); - } - for (; Index < RowCount; Index ++) { - PrintStringAtWithWidth ( - gStatementDimensions.RightColumn - gHelpBlockWidth, - Index + TopRow, - gEmptyString, - gHelpBlockWidth - ); - } - gST->ConOut->SetCursorPosition(gST->ConOut, gStatementDimensions.RightColumn-1, BottomRow); - } else { - if (HelpPageIndex == 0) { - for (Index = 0; Index < RowCount - HelpBottomLine; Index++) { - PrintStringAtWithWidth ( - gStatementDimensions.RightColumn - gHelpBlockWidth, - Index + TopRow, - &HelpString[Index * EachLineWidth], - gHelpBlockWidth - ); - } - } else { - for (Index = 0; (Index < RowCount - HelpBottomLine - HelpHeaderLine) && - (Index + HelpPageIndex * (RowCount - 2) + 1 < HelpLine); Index++) { - PrintStringAtWithWidth ( - gStatementDimensions.RightColumn - gHelpBlockWidth, - Index + TopRow + HelpHeaderLine, - &HelpString[(Index + HelpPageIndex * (RowCount - 2) + 1)* EachLineWidth], - gHelpBlockWidth - ); - } - if (HelpPageIndex == HelpPageCount - 1) { - for (; Index < RowCount - HelpHeaderLine; Index ++) { - PrintStringAtWithWidth ( - gStatementDimensions.RightColumn - gHelpBlockWidth, - Index + TopRow + HelpHeaderLine, - gEmptyString, - gHelpBlockWidth - ); - } - gST->ConOut->SetCursorPosition(gST->ConOut, gStatementDimensions.RightColumn-1, BottomRow); - } - } - } - - // - // Check whether need to print the 'More(D/d)' at the bottom. - // Base on current direct info, here shows aligned to the right side of the column. - // If the direction is multi line and aligned to right side may have problem, so - // add ASSERT code here. - // - if (HelpPageIndex < HelpPageCount - 1 && MultiHelpPage) { - gST->ConOut->SetAttribute (gST->ConOut, GetInfoTextColor ()); - for (Index = 0; Index < HelpBottomLine; Index++) { - ASSERT (HelpBottomLine == 1); - ASSERT (GetStringWidth (HelpBottomString) / 2 < (UINTN) (gHelpBlockWidth - 1)); - PrintStringAtWithWidth ( - gStatementDimensions.RightColumn - gHelpBlockWidth, - BottomRow + Index - HelpBottomLine + 1, - gEmptyString, - gHelpBlockWidth - ); - PrintStringAt ( - gStatementDimensions.RightColumn - GetStringWidth (HelpBottomString) / 2 - 1, - BottomRow + Index - HelpBottomLine + 1, - &HelpBottomString[Index * BottomLineWidth] - ); - } - } - // - // Reset this flag every time we finish using it. - // - Repaint = FALSE; - NewLine = FALSE; - break; - - case CfPrepareToReadKey: - ControlFlag = CfReadKey; - ScreenOperation = UiNoOperation; - break; - - case CfReadKey: - ControlFlag = CfScreenOperation; - - // - // Wait for user's selection - // - while (TRUE) { - Status = gST->ConIn->ReadKeyStroke (gST->ConIn, &Key); - if (!EFI_ERROR (Status)) { - EventType = UIEventKey; - break; - } - - // - // If we encounter error, continue to read another key in. - // - if (Status != EFI_NOT_READY) { - continue; - } - - EventType = UiWaitForEvent(gST->ConIn->WaitForKey); - if (EventType == UIEventKey) { - gST->ConIn->ReadKeyStroke (gST->ConIn, &Key); - } - break; - } - - if (EventType == UIEventDriver) { - gUserInput->Action = BROWSER_ACTION_NONE; - ControlFlag = CfExit; - break; - } - - if (EventType == UIEventTimeOut) { - gUserInput->Action = BROWSER_ACTION_FORM_EXIT; - ControlFlag = CfExit; - break; - } - - switch (Key.UnicodeChar) { - case CHAR_CARRIAGE_RETURN: - if(MenuOption == NULL || MenuOption->GrayOut || MenuOption->ReadOnly) { - ControlFlag = CfReadKey; - break; - } - - ScreenOperation = UiSelect; - gDirection = 0; - break; - - // - // We will push the adjustment of these numeric values directly to the input handler - // NOTE: we won't handle manual input numeric - // - case '+': - case '-': - // - // If the screen has no menu items, and the user didn't select UiReset - // ignore the selection and go back to reading keys. - // - if(IsListEmpty (&gMenuOption) || MenuOption->GrayOut || MenuOption->ReadOnly) { - ControlFlag = CfReadKey; - break; - } - - ASSERT(MenuOption != NULL); - Statement = MenuOption->ThisTag; - if ((Statement->OpCode->OpCode == EFI_IFR_DATE_OP) - || (Statement->OpCode->OpCode == EFI_IFR_TIME_OP) - || ((Statement->OpCode->OpCode == EFI_IFR_NUMERIC_OP) && (GetFieldFromNum(Statement->OpCode) != 0)) - ){ - if (Key.UnicodeChar == '+') { - gDirection = SCAN_RIGHT; - } else { - gDirection = SCAN_LEFT; - } - - Status = ProcessOptions (MenuOption, TRUE, &OptionString, TRUE); - if (OptionString != NULL) { - FreePool (OptionString); - } - if (EFI_ERROR (Status)) { - // - // Repaint to clear possible error prompt pop-up - // - Repaint = TRUE; - NewLine = TRUE; - } else { - ControlFlag = CfExit; - } - } - break; - - case '^': - ScreenOperation = UiUp; - break; - - case 'V': - case 'v': - ScreenOperation = UiDown; - break; - - case ' ': - if(IsListEmpty (&gMenuOption)) { - ControlFlag = CfReadKey; - break; - } - - ASSERT(MenuOption != NULL); - if (MenuOption->ThisTag->OpCode->OpCode == EFI_IFR_CHECKBOX_OP && !MenuOption->GrayOut && !MenuOption->ReadOnly) { - ScreenOperation = UiSelect; - } - break; - - case 'D': - case 'd': - if (!MultiHelpPage) { - ControlFlag = CfReadKey; - break; - } - ControlFlag = CfUpdateHelpString; - HelpPageIndex = HelpPageIndex < HelpPageCount - 1 ? HelpPageIndex + 1 : HelpPageCount - 1; - break; - - case 'U': - case 'u': - if (!MultiHelpPage) { - ControlFlag = CfReadKey; - break; - } - ControlFlag = CfUpdateHelpString; - HelpPageIndex = HelpPageIndex > 0 ? HelpPageIndex - 1 : 0; - break; - - case CHAR_NULL: - for (Index = 0; Index < mScanCodeNumber; Index++) { - if (Key.ScanCode == gScanCodeToOperation[Index].ScanCode) { - ScreenOperation = gScanCodeToOperation[Index].ScreenOperation; - break; - } - } - - if (((FormData->Attribute & HII_DISPLAY_MODAL) != 0) && (Key.ScanCode == SCAN_ESC || Index == mScanCodeNumber)) { - // - // ModalForm has no ESC key and Hot Key. - // - ControlFlag = CfReadKey; - } else if (Index == mScanCodeNumber) { - // - // Check whether Key matches the registered hot key. - // - HotKey = NULL; - HotKey = GetHotKeyFromRegisterList (&Key); - if (HotKey != NULL) { - ScreenOperation = UiHotKey; - } - } - break; - } - break; - - case CfScreenOperation: - if (ScreenOperation != UiReset) { - // - // If the screen has no menu items, and the user didn't select UiReset - // ignore the selection and go back to reading keys. - // - if (IsListEmpty (&gMenuOption)) { - ControlFlag = CfReadKey; - break; - } - } - - for (Index = 0; - Index < sizeof (gScreenOperationToControlFlag) / sizeof (gScreenOperationToControlFlag[0]); - Index++ - ) { - if (ScreenOperation == gScreenOperationToControlFlag[Index].ScreenOperation) { - ControlFlag = gScreenOperationToControlFlag[Index].ControlFlag; - break; - } - } - break; - - case CfUiSelect: - ControlFlag = CfRepaint; - - ASSERT(MenuOption != NULL); - Statement = MenuOption->ThisTag; - if (Statement->OpCode->OpCode == EFI_IFR_TEXT_OP) { - break; - } - - switch (Statement->OpCode->OpCode) { - case EFI_IFR_REF_OP: - case EFI_IFR_ACTION_OP: - case EFI_IFR_RESET_BUTTON_OP: - ControlFlag = CfExit; - break; - - default: - // - // Editable Questions: oneof, ordered list, checkbox, numeric, string, password - // - RefreshKeyHelp (gFormData, Statement, TRUE); - Status = ProcessOptions (MenuOption, TRUE, &OptionString, TRUE); - - if (OptionString != NULL) { - FreePool (OptionString); - } - - if (EFI_ERROR (Status)) { - Repaint = TRUE; - NewLine = TRUE; - RefreshKeyHelp (gFormData, Statement, FALSE); - break; - } else { - ControlFlag = CfExit; - break; - } - } - break; - - case CfUiReset: - // - // We come here when someone press ESC - // If the policy is not exit front page when user press ESC, process here. - // - if (!FormExitPolicy()) { - Repaint = TRUE; - NewLine = TRUE; - ControlFlag = CfRepaint; - break; - } - - // - // When user press ESC, it will try to show another menu, should clean the gSequence info. - // - if (gSequence != 0) { - gSequence = 0; - } - - gUserInput->Action = BROWSER_ACTION_FORM_EXIT; - ControlFlag = CfExit; - break; - - case CfUiHotKey: - ControlFlag = CfRepaint; - - gUserInput->Action = HotKey->Action; - ControlFlag = CfExit; - break; - - case CfUiLeft: - ControlFlag = CfRepaint; - ASSERT(MenuOption != NULL); - if ((MenuOption->ThisTag->OpCode->OpCode == EFI_IFR_DATE_OP) || (MenuOption->ThisTag->OpCode->OpCode == EFI_IFR_TIME_OP)) { - if (MenuOption->Sequence != 0) { - // - // In the middle or tail of the Date/Time op-code set, go left. - // - ASSERT(NewPos != NULL); - NewPos = NewPos->BackLink; - } - } - break; - - case CfUiRight: - ControlFlag = CfRepaint; - ASSERT(MenuOption != NULL); - if ((MenuOption->ThisTag->OpCode->OpCode == EFI_IFR_DATE_OP) || (MenuOption->ThisTag->OpCode->OpCode == EFI_IFR_TIME_OP)) { - if (MenuOption->Sequence != 2) { - // - // In the middle or tail of the Date/Time op-code set, go left. - // - ASSERT(NewPos != NULL); - NewPos = NewPos->ForwardLink; - } - } - break; - - case CfUiUp: - ControlFlag = CfRepaint; - - SavedListEntry = NewPos; - - ASSERT(NewPos != NULL); - // - // Adjust Date/Time position before we advance forward. - // - AdjustDateAndTimePosition (TRUE, &NewPos); - if (NewPos->BackLink != &gMenuOption) { - MenuOption = MENU_OPTION_FROM_LINK (NewPos); - ASSERT (MenuOption != NULL); - NewLine = TRUE; - NewPos = NewPos->BackLink; - - PreviousMenuOption = MENU_OPTION_FROM_LINK (NewPos); - if (PreviousMenuOption->Row == 0) { - UpdateOptionSkipLines (PreviousMenuOption); - } - DistanceValue = PreviousMenuOption->Skip; - Difference = 0; - if (MenuOption->Row >= DistanceValue + TopRow) { - Difference = MoveToNextStatement (TRUE, &NewPos, MenuOption->Row - TopRow - DistanceValue); - } - NextMenuOption = MENU_OPTION_FROM_LINK (NewPos); - - if (Difference < 0) { - // - // We hit the begining MenuOption that can be focused - // so we simply scroll to the top. - // - if (TopOfScreen != gMenuOption.ForwardLink) { - TopOfScreen = gMenuOption.ForwardLink; - Repaint = TRUE; - } else { - // - // Scroll up to the last page when we have arrived at top page. - // - NewPos = &gMenuOption; - TopOfScreen = &gMenuOption; - MenuOption = MENU_OPTION_FROM_LINK (SavedListEntry); - ScreenOperation = UiPageUp; - ControlFlag = CfScreenOperation; - break; - } - } else if (MenuOption->Row < TopRow + DistanceValue + Difference) { - // - // Previous focus MenuOption is above the TopOfScreen, so we need to scroll - // - TopOfScreen = NewPos; - Repaint = TRUE; - SkipValue = 0; - } else if (!IsSelectable (NextMenuOption)) { - // - // Continue to go up until scroll to next page or the selectable option is found. - // - ScreenOperation = UiUp; - ControlFlag = CfScreenOperation; - } - - // - // If we encounter a Date/Time op-code set, rewind to the first op-code of the set. - // - AdjustDateAndTimePosition (TRUE, &TopOfScreen); - AdjustDateAndTimePosition (TRUE, &NewPos); - MenuOption = MENU_OPTION_FROM_LINK (SavedListEntry); - UpdateStatusBar (INPUT_ERROR, FALSE); - } else { - // - // Scroll up to the last page. - // - NewPos = &gMenuOption; - TopOfScreen = &gMenuOption; - MenuOption = MENU_OPTION_FROM_LINK (SavedListEntry); - ScreenOperation = UiPageUp; - ControlFlag = CfScreenOperation; - } - break; - - case CfUiPageUp: - // - // SkipValue means lines is skipped when show the top menu option. - // - ControlFlag = CfRepaint; - - ASSERT(NewPos != NULL); - // - // Already at the first menu option, Check the skip value. - // - if (NewPos->BackLink == &gMenuOption) { - if (SkipValue == 0) { - NewLine = FALSE; - Repaint = FALSE; - } else { - NewLine = TRUE; - Repaint = TRUE; - SkipValue = 0; - } - break; - } - - NewLine = TRUE; - Repaint = TRUE; - - // - // SkipValue > (BottomRow - TopRow + 1) means current menu has more than one - // form of options to be show, so just update the SkipValue to show the next - // parts of options. - // - if (SkipValue > (INTN) (BottomRow - TopRow + 1)) { - SkipValue -= BottomRow - TopRow + 1; - break; - } - - Link = TopOfScreen; - // - // First minus the menu of the top screen, it's value is SkipValue. - // - Index = (BottomRow + 1) - SkipValue; - while ((Index > TopRow) && (Link->BackLink != &gMenuOption)) { - Link = Link->BackLink; - PreviousMenuOption = MENU_OPTION_FROM_LINK (Link); - if (PreviousMenuOption->Row == 0) { - UpdateOptionSkipLines (PreviousMenuOption); - } - if (Index < PreviousMenuOption->Skip) { - break; - } - Index = Index - PreviousMenuOption->Skip; - } - - if ((Link->BackLink == &gMenuOption) && (Index >= TopRow)) { - SkipValue = 0; - if (TopOfScreen == &gMenuOption) { - TopOfScreen = gMenuOption.ForwardLink; - NewPos = gMenuOption.BackLink; - MoveToNextStatement (TRUE, &NewPos, BottomRow - TopRow); - Repaint = FALSE; - } else if (TopOfScreen != Link) { - TopOfScreen = Link; - NewPos = Link; - MoveToNextStatement (FALSE, &NewPos, BottomRow - TopRow); - } else { - // - // Finally we know that NewPos is the last MenuOption can be focused. - // - Repaint = FALSE; - NewPos = Link; - MoveToNextStatement (FALSE, &NewPos, BottomRow - TopRow); - } - } else { - if (Index > TopRow) { - // - // At here, only case "Index < PreviousMenuOption->Skip" can reach here. - // - SkipValue = PreviousMenuOption->Skip - (Index - TopRow); - } else if (Index == TopRow) { - SkipValue = 0; - } else { - SkipValue = TopRow - Index; - } - - // - // Move to the option in Next page. - // - if (TopOfScreen == &gMenuOption) { - NewPos = gMenuOption.BackLink; - MoveToNextStatement (TRUE, &NewPos, BottomRow - TopRow); - } else { - NewPos = Link; - MoveToNextStatement (FALSE, &NewPos, BottomRow - TopRow); - } - - // - // There are more MenuOption needing scrolling up. - // - TopOfScreen = Link; - MenuOption = NULL; - } - - // - // If we encounter a Date/Time op-code set, rewind to the first op-code of the set. - // Don't do this when we are already in the first page. - // - AdjustDateAndTimePosition (TRUE, &TopOfScreen); - AdjustDateAndTimePosition (TRUE, &NewPos); - break; - - case CfUiPageDown: - // - // SkipValue means lines is skipped when show the top menu option. - // - ControlFlag = CfRepaint; - - ASSERT (NewPos != NULL); - if (NewPos->ForwardLink == &gMenuOption) { - NewLine = FALSE; - Repaint = FALSE; - break; - } - - NewLine = TRUE; - Repaint = TRUE; - Link = TopOfScreen; - NextMenuOption = MENU_OPTION_FROM_LINK (Link); - Index = TopRow + NextMenuOption->Skip - SkipValue; - // - // Count to the menu option which will show at the top of the next form. - // - while ((Index <= BottomRow + 1) && (Link->ForwardLink != &gMenuOption)) { - Link = Link->ForwardLink; - NextMenuOption = MENU_OPTION_FROM_LINK (Link); - Index = Index + NextMenuOption->Skip; - } - - if ((Link->ForwardLink == &gMenuOption) && (Index <= BottomRow + 1)) { - // - // Finally we know that NewPos is the last MenuOption can be focused. - // - Repaint = FALSE; - MoveToNextStatement (TRUE, &Link, Index - TopRow); - } else { - // - // Calculate the skip line for top of screen menu. - // - if (Link == TopOfScreen) { - // - // The top of screen menu option occupies the entire form. - // - SkipValue += BottomRow - TopRow + 1; - } else { - SkipValue = NextMenuOption->Skip - (Index - (BottomRow + 1)); - } - - TopOfScreen = Link; - MenuOption = NULL; - // - // Move to the Next selectable menu. - // - MoveToNextStatement (FALSE, &Link, BottomRow - TopRow); - } - - // - // Save the menu as the next highlight menu. - // - NewPos = Link; - - // - // If we encounter a Date/Time op-code set, rewind to the first op-code of the set. - // Don't do this when we are already in the last page. - // - AdjustDateAndTimePosition (TRUE, &TopOfScreen); - AdjustDateAndTimePosition (TRUE, &NewPos); - break; - - case CfUiDown: - // - // SkipValue means lines is skipped when show the top menu option. - // NewPos points to the menu which is highlighted now. - // - ControlFlag = CfRepaint; - - // - // Since the behavior of hitting the down arrow on a Date/Time op-code is intended - // to be one that progresses to the next set of op-codes, we need to advance to the last - // Date/Time op-code and leave the remaining logic in UiDown intact so the appropriate - // checking can be done. The only other logic we need to introduce is that if a Date/Time - // op-code is the last entry in the menu, we need to rewind back to the first op-code of - // the Date/Time op-code. - // - SavedListEntry = NewPos; - AdjustDateAndTimePosition (FALSE, &NewPos); - - if (NewPos->ForwardLink != &gMenuOption) { - MenuOption = MENU_OPTION_FROM_LINK (NewPos); - NewLine = TRUE; - NewPos = NewPos->ForwardLink; - - Difference = 0; - // - // Current menu not at the bottom of the form. - // - if (BottomRow >= MenuOption->Row + MenuOption->Skip) { - // - // Find the next selectable menu. - // - Difference = MoveToNextStatement (FALSE, &NewPos, BottomRow - MenuOption->Row - MenuOption->Skip); - // - // We hit the end of MenuOption that can be focused - // so we simply scroll to the first page. - // - if (Difference < 0) { - // - // Scroll to the first page. - // - if (TopOfScreen != gMenuOption.ForwardLink) { - TopOfScreen = gMenuOption.ForwardLink; - Repaint = TRUE; - MenuOption = NULL; - } else { - MenuOption = MENU_OPTION_FROM_LINK (SavedListEntry); - } - NewPos = gMenuOption.ForwardLink; - MoveToNextStatement (FALSE, &NewPos, BottomRow - TopRow); - - SkipValue = 0; - // - // If we are at the end of the list and sitting on a Date/Time op, rewind to the head. - // - AdjustDateAndTimePosition (TRUE, &TopOfScreen); - AdjustDateAndTimePosition (TRUE, &NewPos); - break; - } - } - NextMenuOption = MENU_OPTION_FROM_LINK (NewPos); - if (NextMenuOption->Row == 0) { - UpdateOptionSkipLines (NextMenuOption); - } - DistanceValue = Difference + NextMenuOption->Skip; - - Temp = MenuOption->Row + MenuOption->Skip + DistanceValue - 1; - if ((MenuOption->Row + MenuOption->Skip == BottomRow + 1) && - (NextMenuOption->ThisTag->OpCode->OpCode == EFI_IFR_DATE_OP || - NextMenuOption->ThisTag->OpCode->OpCode == EFI_IFR_TIME_OP) - ) { - Temp ++; - } - - // - // If we are going to scroll, update TopOfScreen - // - if (Temp > BottomRow) { - do { - // - // Is the current top of screen a zero-advance op-code? - // If so, keep moving forward till we hit a >0 advance op-code - // - SavedMenuOption = MENU_OPTION_FROM_LINK (TopOfScreen); - - // - // If bottom op-code is more than one line or top op-code is more than one line - // - if ((DistanceValue > 1) || (SavedMenuOption->Skip > 1)) { - // - // Is the bottom op-code greater than or equal in size to the top op-code? - // - if ((Temp - BottomRow) >= (SavedMenuOption->Skip - SkipValue)) { - // - // Skip the top op-code - // - TopOfScreen = TopOfScreen->ForwardLink; - Difference = (Temp - BottomRow) - (SavedMenuOption->Skip - SkipValue); - - SavedMenuOption = MENU_OPTION_FROM_LINK (TopOfScreen); - - // - // If we have a remainder, skip that many more op-codes until we drain the remainder - // - while (Difference >= (INTN) SavedMenuOption->Skip) { - // - // Since the Difference is greater than or equal to this op-code's skip value, skip it - // - Difference = Difference - (INTN) SavedMenuOption->Skip; - TopOfScreen = TopOfScreen->ForwardLink; - SavedMenuOption = MENU_OPTION_FROM_LINK (TopOfScreen); - } - // - // Since we will act on this op-code in the next routine, and increment the - // SkipValue, set the skips to one less than what is required. - // - SkipValue = Difference - 1; - } else { - // - // Since we will act on this op-code in the next routine, and increment the - // SkipValue, set the skips to one less than what is required. - // - SkipValue += (Temp - BottomRow) - 1; - } - } else { - if ((SkipValue + 1) == (INTN) SavedMenuOption->Skip) { - TopOfScreen = TopOfScreen->ForwardLink; - break; - } - } - // - // If the op-code at the top of the screen is more than one line, let's not skip it yet - // Let's set a skip flag to smoothly scroll the top of the screen. - // - if (SavedMenuOption->Skip > 1) { - if (SavedMenuOption == NextMenuOption) { - SkipValue = 0; - } else { - SkipValue++; - } - } else if (SavedMenuOption->Skip == 1) { - SkipValue = 0; - } else { - SkipValue = 0; - TopOfScreen = TopOfScreen->ForwardLink; - } - } while (SavedMenuOption->Skip == 0); - - Repaint = TRUE; - } else if (!IsSelectable (NextMenuOption)) { - // - // Continue to go down until scroll to next page or the selectable option is found. - // - ScreenOperation = UiDown; - ControlFlag = CfScreenOperation; - } - - MenuOption = MENU_OPTION_FROM_LINK (SavedListEntry); - - UpdateStatusBar (INPUT_ERROR, FALSE); - - } else { - // - // Scroll to the first page. - // - if (TopOfScreen != gMenuOption.ForwardLink) { - TopOfScreen = gMenuOption.ForwardLink; - Repaint = TRUE; - MenuOption = NULL; - } else { - // - // Need to remove the current highlight menu. - // MenuOption saved the last highlight menu info. - // - MenuOption = MENU_OPTION_FROM_LINK (SavedListEntry); - } - - SkipValue = 0; - NewLine = TRUE; - // - // Get the next highlight menu. - // - NewPos = gMenuOption.ForwardLink; - MoveToNextStatement (FALSE, &NewPos, BottomRow - TopRow); - } - - // - // If we are at the end of the list and sitting on a Date/Time op, rewind to the head. - // - AdjustDateAndTimePosition (TRUE, &TopOfScreen); - AdjustDateAndTimePosition (TRUE, &NewPos); - break; - - case CfUiNoOperation: - ControlFlag = CfRepaint; - break; - - case CfExit: - gST->ConOut->SetAttribute (gST->ConOut, EFI_TEXT_ATTR (EFI_LIGHTGRAY, EFI_BLACK)); - if (HelpString != NULL) { - FreePool (HelpString); - } - if (HelpHeaderString != NULL) { - FreePool (HelpHeaderString); - } - if (HelpBottomString != NULL) { - FreePool (HelpBottomString); - } - return EFI_SUCCESS; - - default: - break; - } - } -} - -/** - - Base on the browser status info to show an pop up message. - -**/ -VOID -BrowserStatusProcess ( - VOID - ) -{ - CHAR16 *ErrorInfo; - EFI_INPUT_KEY Key; - - if (gFormData->BrowserStatus == BROWSER_SUCCESS) { - return; - } - - if (gFormData->ErrorString != NULL) { - ErrorInfo = gFormData->ErrorString; - } else { - switch (gFormData->BrowserStatus) { - case BROWSER_SUBMIT_FAIL: - ErrorInfo = gSaveFailed; - break; - - case BROWSER_NO_SUBMIT_IF: - ErrorInfo = gNoSubmitIf; - break; - - case BROWSER_FORM_NOT_FOUND: - ErrorInfo = gFormNotFound; - break; - - case BROWSER_FORM_SUPPRESS: - ErrorInfo = gFormSuppress; - break; - - case BROWSER_PROTOCOL_NOT_FOUND: - ErrorInfo = gProtocolNotFound; - break; - - default: - ErrorInfo = gBrwoserError; - break; - } - } - - // - // Error occur, prompt error message. - // - do { - CreateDialog (&Key, gEmptyString, ErrorInfo, gPressEnter, gEmptyString, NULL); - } while (Key.UnicodeChar != CHAR_CARRIAGE_RETURN); -} - -/** - Display one form, and return user input. - - @param FormData Form Data to be shown. - @param UserInputData User input data. - - @retval EFI_SUCCESS 1.Form Data is shown, and user input is got. - 2.Error info has show and return. - @retval EFI_INVALID_PARAMETER The input screen dimension is not valid - @retval EFI_NOT_FOUND New form data has some error. -**/ -EFI_STATUS -EFIAPI -FormDisplay ( - IN FORM_DISPLAY_ENGINE_FORM *FormData, - OUT USER_INPUT *UserInputData - ) -{ - EFI_STATUS Status; - - ASSERT (FormData != NULL); - if (FormData == NULL) { - return EFI_INVALID_PARAMETER; - } - - gUserInput = UserInputData; - gFormData = FormData; - - // - // Process the status info first. - // - BrowserStatusProcess(); - if (UserInputData == NULL) { - // - // UserInputData == NULL, means only need to print the error info, return here. - // - return EFI_SUCCESS; - } - - ConvertStatementToMenu(); - - Status = DisplayPageFrame (FormData, &gStatementDimensions); - if (EFI_ERROR (Status)) { - return Status; - } - - // - // Check whether layout is changed. - // - if (mIsFirstForm - || (gOldFormEntry.HiiHandle != FormData->HiiHandle) - || (!CompareGuid (&gOldFormEntry.FormSetGuid, &FormData->FormSetGuid)) - || (gOldFormEntry.FormId != FormData->FormId)) { - mStatementLayoutIsChanged = TRUE; - } else { - mStatementLayoutIsChanged = FALSE; - } - - Status = UiDisplayMenu(FormData); - - // - // Backup last form info. - // - mIsFirstForm = FALSE; - gOldFormEntry.HiiHandle = FormData->HiiHandle; - CopyGuid (&gOldFormEntry.FormSetGuid, &FormData->FormSetGuid); - gOldFormEntry.FormId = FormData->FormId; - - return Status; -} - -/** - Clear Screen to the initial state. -**/ -VOID -EFIAPI -DriverClearDisplayPage ( - VOID - ) -{ - ClearDisplayPage (); - mIsFirstForm = TRUE; -} - -/** - Set Buffer to Value for Size bytes. - - @param Buffer Memory to set. - @param Size Number of bytes to set - @param Value Value of the set operation. - -**/ -VOID -SetUnicodeMem ( - IN VOID *Buffer, - IN UINTN Size, - IN CHAR16 Value - ) -{ - CHAR16 *Ptr; - - Ptr = Buffer; - while ((Size--) != 0) { - *(Ptr++) = Value; - } -} - -/** - Initialize Setup Browser driver. - - @param ImageHandle The image handle. - @param SystemTable The system table. - - @retval EFI_SUCCESS The Setup Browser module is initialized correctly.. - @return Other value if failed to initialize the Setup Browser module. - -**/ -EFI_STATUS -EFIAPI -InitializeDisplayEngine ( - IN EFI_HANDLE ImageHandle, - IN EFI_SYSTEM_TABLE *SystemTable - ) -{ - EFI_STATUS Status; - EFI_INPUT_KEY HotKey; - EFI_STRING NewString; - EDKII_FORM_BROWSER_EXTENSION2_PROTOCOL *FormBrowserEx2; - - // - // Publish our HII data - // - gHiiHandle = HiiAddPackages ( - &gDisplayEngineGuid, - ImageHandle, - DisplayEngineStrings, - NULL - ); - ASSERT (gHiiHandle != NULL); - - // - // Install Form Display protocol - // - Status = gBS->InstallProtocolInterface ( - &mPrivateData.Handle, - &gEdkiiFormDisplayEngineProtocolGuid, - EFI_NATIVE_INTERFACE, - &mPrivateData.FromDisplayProt - ); - ASSERT_EFI_ERROR (Status); - - InitializeDisplayStrings(); - - ZeroMem (&gHighligthMenuInfo, sizeof (gHighligthMenuInfo)); - ZeroMem (&gOldFormEntry, sizeof (gOldFormEntry)); - - // - // Use BrowserEx2 protocol to register HotKey. - // - Status = gBS->LocateProtocol (&gEdkiiFormBrowserEx2ProtocolGuid, NULL, (VOID **) &FormBrowserEx2); - if (!EFI_ERROR (Status)) { - // - // Register the default HotKey F9 and F10 again. - // - HotKey.UnicodeChar = CHAR_NULL; - HotKey.ScanCode = SCAN_F10; - NewString = HiiGetString (gHiiHandle, STRING_TOKEN (FUNCTION_TEN_STRING), NULL); - ASSERT (NewString != NULL); - FormBrowserEx2->RegisterHotKey (&HotKey, BROWSER_ACTION_SUBMIT, 0, NewString); - - HotKey.ScanCode = SCAN_F9; - NewString = HiiGetString (gHiiHandle, STRING_TOKEN (FUNCTION_NINE_STRING), NULL); - ASSERT (NewString != NULL); - FormBrowserEx2->RegisterHotKey (&HotKey, BROWSER_ACTION_DEFAULT, EFI_HII_DEFAULT_CLASS_STANDARD, NewString); - } - - return EFI_SUCCESS; -} - -/** - This is the default unload handle for display core drivers. - - @param[in] ImageHandle The drivers' driver image. - - @retval EFI_SUCCESS The image is unloaded. - @retval Others Failed to unload the image. - -**/ -EFI_STATUS -EFIAPI -UnloadDisplayEngine ( - IN EFI_HANDLE ImageHandle - ) -{ - HiiRemovePackages(gHiiHandle); - - FreeDisplayStrings (); - - return EFI_SUCCESS; -} diff --git a/MdeModulePkg/Universal/DisplayEngineDxe/FormDisplay.h b/MdeModulePkg/Universal/DisplayEngineDxe/FormDisplay.h deleted file mode 100644 index 45bcadc7e6..0000000000 --- a/MdeModulePkg/Universal/DisplayEngineDxe/FormDisplay.h +++ /dev/null @@ -1,589 +0,0 @@ -/** @file - FormDiplay protocol to show Form - -Copyright (c) 2013, Intel Corporation. All rights reserved.
-This program and the accompanying materials are licensed and made available under -the terms and conditions of the BSD License that accompanies this distribution. -The full text of the license may be found at -http://opensource.org/licenses/bsd-license.php. - -THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, -WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. - -**/ - -#ifndef __FORM_DISPLAY_H__ -#define __FORM_DISPLAY_H__ - - -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -#include - -// -// This is the generated header file which includes whatever needs to be exported (strings + IFR) -// -extern UINT8 DisplayEngineStrings[]; -extern EFI_SCREEN_DESCRIPTOR gStatementDimensions; -extern USER_INPUT *gUserInput; -extern FORM_DISPLAY_ENGINE_FORM *gFormData; -extern EFI_HII_HANDLE gHiiHandle; -extern UINT16 gDirection; -extern LIST_ENTRY gMenuOption; - -// -// Browser Global Strings -// -extern CHAR16 *gSaveFailed; -extern CHAR16 *gPromptForData; -extern CHAR16 *gPromptForPassword; -extern CHAR16 *gPromptForNewPassword; -extern CHAR16 *gConfirmPassword; -extern CHAR16 *gConfirmError; -extern CHAR16 *gPassowordInvalid; -extern CHAR16 *gPressEnter; -extern CHAR16 *gEmptyString; -extern CHAR16 *gMiniString; -extern CHAR16 *gOptionMismatch; -extern CHAR16 *gFormSuppress; -extern CHAR16 *gProtocolNotFound; - -extern CHAR16 gPromptBlockWidth; -extern CHAR16 gOptionBlockWidth; -extern CHAR16 gHelpBlockWidth; -extern CHAR16 *mUnknownString; - -// -// Screen definitions -// - -#define LEFT_SKIPPED_COLUMNS 3 -#define SCROLL_ARROW_HEIGHT 1 -#define POPUP_PAD_SPACE_COUNT 5 -#define POPUP_FRAME_WIDTH 2 - -// -// Display definitions -// -#define LEFT_ONEOF_DELIMITER L'<' -#define RIGHT_ONEOF_DELIMITER L'>' - -#define LEFT_NUMERIC_DELIMITER L'[' -#define RIGHT_NUMERIC_DELIMITER L']' - -#define LEFT_CHECKBOX_DELIMITER L'[' -#define RIGHT_CHECKBOX_DELIMITER L']' - -#define CHECK_ON L'X' -#define CHECK_OFF L' ' - -#define TIME_SEPARATOR L':' -#define DATE_SEPARATOR L'/' - -#define SUBTITLE_INDENT 2 - -// -// This is the Input Error Message -// -#define INPUT_ERROR 1 - -// -// This is the NV RAM update required Message -// -#define NV_UPDATE_REQUIRED 2 -// -// Time definitions -// -#define ONE_SECOND 10000000 - -// -// It take 23 characters including the NULL to print a 64 bits number with "[" and "]". -// pow(2, 64) = [18446744073709551616] -// -#define MAX_NUMERIC_INPUT_WIDTH 23 - -#define EFI_HII_EXPRESSION_INCONSISTENT_IF 0 -#define EFI_HII_EXPRESSION_NO_SUBMIT_IF 1 -#define EFI_HII_EXPRESSION_GRAY_OUT_IF 2 -#define EFI_HII_EXPRESSION_SUPPRESS_IF 3 -#define EFI_HII_EXPRESSION_DISABLE_IF 4 - -// -// Character definitions -// -#define CHAR_SPACE 0x0020 - -#define FORM_DISPLAY_DRIVER_SIGNATURE SIGNATURE_32 ('F', 'D', 'D', 'V') -typedef struct { - UINT32 Signature; - - EFI_HANDLE Handle; - - // - // Produced protocol - // - EDKII_FORM_DISPLAY_ENGINE_PROTOCOL FromDisplayProt; -} FORM_DISPLAY_DRIVER_PRIVATE_DATA; - - -typedef enum { - UiNoOperation, - UiSelect, - UiUp, - UiDown, - UiLeft, - UiRight, - UiReset, - UiPrevious, - UiPageUp, - UiPageDown, - UiHotKey, - UiMaxOperation -} UI_SCREEN_OPERATION; - -typedef enum { - CfInitialization, - CfCheckSelection, - CfRepaint, - CfRefreshHighLight, - CfUpdateHelpString, - CfPrepareToReadKey, - CfReadKey, - CfScreenOperation, - CfUiSelect, - CfUiReset, - CfUiLeft, - CfUiRight, - CfUiUp, - CfUiPageUp, - CfUiPageDown, - CfUiDown, - CfUiDefault, - CfUiNoOperation, - CfExit, - CfUiHotKey, - CfMaxControlFlag -} UI_CONTROL_FLAG; - -typedef enum { - UIEventNone, - UIEventKey, - UIEventTimeOut, - UIEventDriver -} UI_EVENT_TYPE; - -typedef struct { - UINT16 ScanCode; - UI_SCREEN_OPERATION ScreenOperation; -} SCAN_CODE_TO_SCREEN_OPERATION; - -typedef struct { - UI_SCREEN_OPERATION ScreenOperation; - UI_CONTROL_FLAG ControlFlag; -} SCREEN_OPERATION_T0_CONTROL_FLAG; - -typedef struct { - EFI_QUESTION_ID QuestionId; - UINT16 DisplayRow; -} DISPLAY_HIGHLIGHT_MENU_INFO; - -#define UI_MENU_OPTION_SIGNATURE SIGNATURE_32 ('u', 'i', 'm', 'm') - -typedef struct { - UINTN Signature; - LIST_ENTRY Link; - - EFI_HII_HANDLE Handle; - FORM_DISPLAY_ENGINE_STATEMENT *ThisTag; - UINT16 EntryNumber; - - UINTN Row; - UINTN Col; - UINTN OptCol; - CHAR16 *Description; - UINTN Skip; // Number of lines - - // - // Display item sequence for date/time - // Date: Month/Day/Year - // Sequence: 0 1 2 - // - // Time: Hour : Minute : Second - // Sequence: 0 1 2 - // - // - UINTN Sequence; - - BOOLEAN GrayOut; - BOOLEAN ReadOnly; - - // - // Whether user could change value of this item - // - BOOLEAN IsQuestion; - BOOLEAN NestInStatement; -} UI_MENU_OPTION; - -#define MENU_OPTION_FROM_LINK(a) CR (a, UI_MENU_OPTION, Link, UI_MENU_OPTION_SIGNATURE) - -/** - Print Question Value according to it's storage width and display attributes. - - @param Question The Question to be printed. - @param FormattedNumber Buffer for output string. - @param BufferSize The FormattedNumber buffer size in bytes. - - @retval EFI_SUCCESS Print success. - @retval EFI_BUFFER_TOO_SMALL Buffer size is not enough for formatted number. - -**/ -EFI_STATUS -PrintFormattedNumber ( - IN FORM_DISPLAY_ENGINE_STATEMENT *Question, - IN OUT CHAR16 *FormattedNumber, - IN UINTN BufferSize - ); - -/** - Set value of a data element in an Array by its Index. - - @param Array The data array. - @param Type Type of the data in this array. - @param Index Zero based index for data in this array. - @param Value The value to be set. - -**/ -VOID -SetArrayData ( - IN VOID *Array, - IN UINT8 Type, - IN UINTN Index, - IN UINT64 Value - ); - -/** - Return data element in an Array by its Index. - - @param Array The data array. - @param Type Type of the data in this array. - @param Index Zero based index for data in this array. - - @retval Value The data to be returned - -**/ -UINT64 -GetArrayData ( - IN VOID *Array, - IN UINT8 Type, - IN UINTN Index - ); - -/** - Search an Option of a Question by its value. - - @param Question The Question - @param OptionValue Value for Option to be searched. - - @retval Pointer Pointer to the found Option. - @retval NULL Option not found. - -**/ -DISPLAY_QUESTION_OPTION * -ValueToOption ( - IN FORM_DISPLAY_ENGINE_STATEMENT *Question, - IN EFI_HII_VALUE *OptionValue - ); - -/** - Compare two Hii value. - - @param Value1 Expression value to compare on left-hand. - @param Value2 Expression value to compare on right-hand. - @param Result Return value after compare. - retval 0 Two operators equal. - return Positive value if Value1 is greater than Value2. - retval Negative value if Value1 is less than Value2. - @param HiiHandle Only required for string compare. - - @retval other Could not perform compare on two values. - @retval EFI_SUCCESS Compare the value success. - -**/ -EFI_STATUS -CompareHiiValue ( - IN EFI_HII_VALUE *Value1, - IN EFI_HII_VALUE *Value2, - OUT INTN *Result, - IN EFI_HII_HANDLE HiiHandle OPTIONAL - ); - -/** - Draw a pop up windows based on the dimension, number of lines and - strings specified. - - @param RequestedWidth The width of the pop-up. - @param NumberOfLines The number of lines. - @param ... A series of text strings that displayed in the pop-up. - -**/ -VOID -EFIAPI -CreateMultiStringPopUp ( - IN UINTN RequestedWidth, - IN UINTN NumberOfLines, - ... - ); - -/** - Will copy LineWidth amount of a string in the OutputString buffer and return the - number of CHAR16 characters that were copied into the OutputString buffer. - The output string format is: - Glyph Info + String info + '\0'. - - In the code, it deals \r,\n,\r\n same as \n\r, also it not process the \r or \g. - - @param InputString String description for this option. - @param LineWidth Width of the desired string to extract in CHAR16 - characters - @param GlyphWidth The glyph width of the begin of the char in the string. - @param Index Where in InputString to start the copy process - @param OutputString Buffer to copy the string into - - @return Returns the number of CHAR16 characters that were copied into the OutputString - buffer, include extra glyph info and '\0' info. - -**/ -UINT16 -GetLineByWidth ( - IN CHAR16 *InputString, - IN UINT16 LineWidth, - IN OUT UINT16 *GlyphWidth, - IN OUT UINTN *Index, - OUT CHAR16 **OutputString - ); - - -/** - Get the string based on the StringId and HII Package List Handle. - - @param Token The String's ID. - @param HiiHandle The Hii handle for this string package. - - @return The output string. - -**/ -CHAR16 * -GetToken ( - IN EFI_STRING_ID Token, - IN EFI_HII_HANDLE HiiHandle - ); - -/** - Count the storage space of a Unicode string. - - This function handles the Unicode string with NARROW_CHAR - and WIDE_CHAR control characters. NARROW_HCAR and WIDE_CHAR - does not count in the resultant output. If a WIDE_CHAR is - hit, then 2 Unicode character will consume an output storage - space with size of CHAR16 till a NARROW_CHAR is hit. - - If String is NULL, then ASSERT (). - - @param String The input string to be counted. - - @return Storage space for the input string. - -**/ -UINTN -GetStringWidth ( - IN CHAR16 *String - ); - -/** - This routine reads a numeric value from the user input. - - @param MenuOption Pointer to the current input menu. - - @retval EFI_SUCCESS If numerical input is read successfully - @retval EFI_DEVICE_ERROR If operation fails - -**/ -EFI_STATUS -GetNumericInput ( - IN UI_MENU_OPTION *MenuOption - ); - -/** - Get string or password input from user. - - @param MenuOption Pointer to the current input menu. - @param Prompt The prompt string shown on popup window. - @param StringPtr Old user input and destination for use input string. - - @retval EFI_SUCCESS If string input is read successfully - @retval EFI_DEVICE_ERROR If operation fails - -**/ -EFI_STATUS -ReadString ( - IN UI_MENU_OPTION *MenuOption, - IN CHAR16 *Prompt, - IN OUT CHAR16 *StringPtr - ); - -/** - Draw a pop up windows based on the dimension, number of lines and - strings specified. - - @param RequestedWidth The width of the pop-up. - @param NumberOfLines The number of lines. - @param Marker The variable argument list for the list of string to be printed. - -**/ -VOID -CreateSharedPopUp ( - IN UINTN RequestedWidth, - IN UINTN NumberOfLines, - IN VA_LIST Marker - ); - -/** - Wait for a key to be pressed by user. - - @param Key The key which is pressed by user. - - @retval EFI_SUCCESS The function always completed successfully. - -**/ -EFI_STATUS -WaitForKeyStroke ( - OUT EFI_INPUT_KEY *Key - ); - -/** - Get selection for OneOf and OrderedList (Left/Right will be ignored). - - @param MenuOption Pointer to the current input menu. - - @retval EFI_SUCCESS If Option input is processed successfully - @retval EFI_DEVICE_ERROR If operation fails - -**/ -EFI_STATUS -GetSelectionInputPopUp ( - IN UI_MENU_OPTION *MenuOption - ); - -/** - Process the help string: Split StringPtr to several lines of strings stored in - FormattedString and the glyph width of each line cannot exceed gHelpBlockWidth. - - @param StringPtr The entire help string. - @param FormattedString The oupput formatted string. - @param EachLineWidth The max string length of each line in the formatted string. - @param RowCount TRUE: if Question is selected. - -**/ -UINTN -ProcessHelpString ( - IN CHAR16 *StringPtr, - OUT CHAR16 **FormattedString, - OUT UINT16 *EachLineWidth, - IN UINTN RowCount - ); - -/** - Process a Question's Option (whether selected or un-selected). - - @param MenuOption The MenuOption for this Question. - @param Selected TRUE: if Question is selected. - @param OptionString Pointer of the Option String to be displayed. - @param SkipErrorValue Whether need to return when value without option for it. - - @retval EFI_SUCCESS Question Option process success. - @retval Other Question Option process fail. - -**/ -EFI_STATUS -ProcessOptions ( - IN UI_MENU_OPTION *MenuOption, - IN BOOLEAN Selected, - OUT CHAR16 **OptionString, - IN BOOLEAN SkipErrorValue - ); - -/** - Set Buffer to Value for Size bytes. - - @param Buffer Memory to set. - @param Size Number of bytes to set - @param Value Value of the set operation. - -**/ -VOID -SetUnicodeMem ( - IN VOID *Buffer, - IN UINTN Size, - IN CHAR16 Value - ); - -/** - Display one form, and return user input. - - @param FormData Form Data to be shown. - @param UserInputData User input data. - - @retval EFI_SUCCESS Form Data is shown, and user input is got. -**/ -EFI_STATUS -EFIAPI -FormDisplay ( - IN FORM_DISPLAY_ENGINE_FORM *FormData, - OUT USER_INPUT *UserInputData - ); - -/** - Clear Screen to the initial state. -**/ -VOID -EFIAPI -DriverClearDisplayPage ( - VOID - ); - -/** - Exit Display and Clear Screen to the original state. - -**/ -VOID -EFIAPI -ExitDisplay ( - VOID - ); - -/** - Process validate for one question. - - @param Question The question which need to validate. - - @retval EFI_SUCCESS Question Option process success. - @retval Other Question Option process fail. - -**/ -EFI_STATUS -ValidateQuestion ( - IN FORM_DISPLAY_ENGINE_STATEMENT *Question - ); - -#endif diff --git a/MdeModulePkg/Universal/DisplayEngineDxe/FormDisplayStr.uni b/MdeModulePkg/Universal/DisplayEngineDxe/FormDisplayStr.uni deleted file mode 100644 index 0ee7f46302..0000000000 Binary files a/MdeModulePkg/Universal/DisplayEngineDxe/FormDisplayStr.uni and /dev/null differ diff --git a/MdeModulePkg/Universal/DisplayEngineDxe/InputHandler.c b/MdeModulePkg/Universal/DisplayEngineDxe/InputHandler.c deleted file mode 100644 index a58e12f12c..0000000000 --- a/MdeModulePkg/Universal/DisplayEngineDxe/InputHandler.c +++ /dev/null @@ -1,1531 +0,0 @@ -/** @file -Implementation for handling user input from the User Interfaces. - -Copyright (c) 2004 - 2012, Intel Corporation. All rights reserved.
-This program and the accompanying materials -are licensed and made available under the terms and conditions of the BSD License -which accompanies this distribution. The full text of the license may be found at -http://opensource.org/licenses/bsd-license.php - -THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, -WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. - -**/ - -#include "FormDisplay.h" - -/** - Get maximum and minimum info from this opcode. - - @param OpCode Pointer to the current input opcode. - @param Minimum The minimum size info for this opcode. - @param Maximum The maximum size info for this opcode. - -**/ -VOID -GetFieldFromOp ( - IN EFI_IFR_OP_HEADER *OpCode, - OUT UINTN *Minimum, - OUT UINTN *Maximum - ) -{ - EFI_IFR_STRING *StringOp; - EFI_IFR_PASSWORD *PasswordOp; - if (OpCode->OpCode == EFI_IFR_STRING_OP) { - StringOp = (EFI_IFR_STRING *) OpCode; - *Minimum = StringOp->MinSize; - *Maximum = StringOp->MaxSize; - } else if (OpCode->OpCode == EFI_IFR_PASSWORD_OP) { - PasswordOp = (EFI_IFR_PASSWORD *) OpCode; - *Minimum = PasswordOp->MinSize; - *Maximum = PasswordOp->MaxSize; - } else { - *Minimum = 0; - *Maximum = 0; - } -} - -/** - Get string or password input from user. - - @param MenuOption Pointer to the current input menu. - @param Prompt The prompt string shown on popup window. - @param StringPtr Old user input and destination for use input string. - - @retval EFI_SUCCESS If string input is read successfully - @retval EFI_DEVICE_ERROR If operation fails - -**/ -EFI_STATUS -ReadString ( - IN UI_MENU_OPTION *MenuOption, - IN CHAR16 *Prompt, - IN OUT CHAR16 *StringPtr - ) -{ - EFI_STATUS Status; - EFI_INPUT_KEY Key; - CHAR16 NullCharacter; - UINTN ScreenSize; - CHAR16 Space[2]; - CHAR16 KeyPad[2]; - CHAR16 *TempString; - CHAR16 *BufferedString; - UINTN Index; - UINTN Index2; - UINTN Count; - UINTN Start; - UINTN Top; - UINTN DimensionsWidth; - UINTN DimensionsHeight; - UINTN CurrentCursor; - BOOLEAN CursorVisible; - UINTN Minimum; - UINTN Maximum; - FORM_DISPLAY_ENGINE_STATEMENT *Question; - BOOLEAN IsPassword; - - DimensionsWidth = gStatementDimensions.RightColumn - gStatementDimensions.LeftColumn; - DimensionsHeight = gStatementDimensions.BottomRow - gStatementDimensions.TopRow; - - NullCharacter = CHAR_NULL; - ScreenSize = GetStringWidth (Prompt) / sizeof (CHAR16); - Space[0] = L' '; - Space[1] = CHAR_NULL; - - Question = MenuOption->ThisTag; - GetFieldFromOp(Question->OpCode, &Minimum, &Maximum); - - if (Question->OpCode->OpCode == EFI_IFR_PASSWORD_OP) { - IsPassword = TRUE; - } else { - IsPassword = FALSE; - } - - TempString = AllocateZeroPool ((Maximum + 1)* sizeof (CHAR16)); - ASSERT (TempString); - - if (ScreenSize < (Maximum + 1)) { - ScreenSize = Maximum + 1; - } - - if ((ScreenSize + 2) > DimensionsWidth) { - ScreenSize = DimensionsWidth - 2; - } - - BufferedString = AllocateZeroPool (ScreenSize * 2); - ASSERT (BufferedString); - - Start = (DimensionsWidth - ScreenSize - 2) / 2 + gStatementDimensions.LeftColumn + 1; - Top = ((DimensionsHeight - 6) / 2) + gStatementDimensions.TopRow - 1; - - // - // Display prompt for string - // - // CreateDialog (NULL, "", Prompt, Space, "", NULL); - CreateMultiStringPopUp (ScreenSize, 4, &NullCharacter, Prompt, Space, &NullCharacter); - gST->ConOut->SetAttribute (gST->ConOut, EFI_TEXT_ATTR (EFI_BLACK, EFI_LIGHTGRAY)); - - CursorVisible = gST->ConOut->Mode->CursorVisible; - gST->ConOut->EnableCursor (gST->ConOut, TRUE); - - CurrentCursor = GetStringWidth (StringPtr) / 2 - 1; - if (CurrentCursor != 0) { - // - // Show the string which has beed saved before. - // - SetUnicodeMem (BufferedString, ScreenSize - 1, L' '); - PrintStringAt (Start + 1, Top + 3, BufferedString); - - if ((GetStringWidth (StringPtr) / 2) > (DimensionsWidth - 2)) { - Index = (GetStringWidth (StringPtr) / 2) - DimensionsWidth + 2; - } else { - Index = 0; - } - - if (IsPassword) { - gST->ConOut->SetCursorPosition (gST->ConOut, Start + 1, Top + 3); - } - - for (Count = 0; Index + 1 < GetStringWidth (StringPtr) / 2; Index++, Count++) { - BufferedString[Count] = StringPtr[Index]; - - if (IsPassword) { - PrintCharAt ((UINTN)-1, (UINTN)-1, L'*'); - } - } - - if (!IsPassword) { - PrintStringAt (Start + 1, Top + 3, BufferedString); - } - - gST->ConOut->SetAttribute (gST->ConOut, EFI_TEXT_ATTR (EFI_LIGHTGRAY, EFI_BLACK)); - gST->ConOut->SetCursorPosition (gST->ConOut, Start + GetStringWidth (StringPtr) / 2, Top + 3); - } - - do { - Status = WaitForKeyStroke (&Key); - ASSERT_EFI_ERROR (Status); - - gST->ConOut->SetAttribute (gST->ConOut, EFI_TEXT_ATTR (EFI_BLACK, EFI_LIGHTGRAY)); - switch (Key.UnicodeChar) { - case CHAR_NULL: - switch (Key.ScanCode) { - case SCAN_LEFT: - if (CurrentCursor > 0) { - CurrentCursor--; - } - break; - - case SCAN_RIGHT: - if (CurrentCursor < (GetStringWidth (StringPtr) / 2 - 1)) { - CurrentCursor++; - } - break; - - case SCAN_ESC: - FreePool (TempString); - FreePool (BufferedString); - gST->ConOut->SetAttribute (gST->ConOut, EFI_TEXT_ATTR (EFI_LIGHTGRAY, EFI_BLACK)); - gST->ConOut->EnableCursor (gST->ConOut, CursorVisible); - return EFI_DEVICE_ERROR; - - default: - break; - } - - break; - - case CHAR_CARRIAGE_RETURN: - if (GetStringWidth (StringPtr) >= ((Minimum + 1) * sizeof (CHAR16))) { - - FreePool (TempString); - FreePool (BufferedString); - gST->ConOut->SetAttribute (gST->ConOut, EFI_TEXT_ATTR (EFI_LIGHTGRAY, EFI_BLACK)); - gST->ConOut->EnableCursor (gST->ConOut, CursorVisible); - return EFI_SUCCESS; - } else { - // - // Simply create a popup to tell the user that they had typed in too few characters. - // To save code space, we can then treat this as an error and return back to the menu. - // - do { - CreateDialog (&Key, &NullCharacter, gMiniString, gPressEnter, &NullCharacter, NULL); - } while (Key.UnicodeChar != CHAR_CARRIAGE_RETURN); - - FreePool (TempString); - FreePool (BufferedString); - gST->ConOut->SetAttribute (gST->ConOut, EFI_TEXT_ATTR (EFI_LIGHTGRAY, EFI_BLACK)); - gST->ConOut->EnableCursor (gST->ConOut, CursorVisible); - return EFI_DEVICE_ERROR; - } - - break; - - case CHAR_BACKSPACE: - if (StringPtr[0] != CHAR_NULL && CurrentCursor != 0) { - for (Index = 0; Index < CurrentCursor - 1; Index++) { - TempString[Index] = StringPtr[Index]; - } - Count = GetStringWidth (StringPtr) / 2 - 1; - if (Count >= CurrentCursor) { - for (Index = CurrentCursor - 1, Index2 = CurrentCursor; Index2 < Count; Index++, Index2++) { - TempString[Index] = StringPtr[Index2]; - } - TempString[Index] = CHAR_NULL; - } - // - // Effectively truncate string by 1 character - // - StrCpy (StringPtr, TempString); - CurrentCursor --; - } - - default: - // - // If it is the beginning of the string, don't worry about checking maximum limits - // - if ((StringPtr[0] == CHAR_NULL) && (Key.UnicodeChar != CHAR_BACKSPACE)) { - StrnCpy (StringPtr, &Key.UnicodeChar, 1); - CurrentCursor++; - } else if ((GetStringWidth (StringPtr) < ((Maximum + 1) * sizeof (CHAR16))) && (Key.UnicodeChar != CHAR_BACKSPACE)) { - KeyPad[0] = Key.UnicodeChar; - KeyPad[1] = CHAR_NULL; - Count = GetStringWidth (StringPtr) / 2 - 1; - if (CurrentCursor < Count) { - for (Index = 0; Index < CurrentCursor; Index++) { - TempString[Index] = StringPtr[Index]; - } - TempString[Index] = CHAR_NULL; - StrCat (TempString, KeyPad); - StrCat (TempString, StringPtr + CurrentCursor); - StrCpy (StringPtr, TempString); - } else { - StrCat (StringPtr, KeyPad); - } - CurrentCursor++; - } - - // - // If the width of the input string is now larger than the screen, we nee to - // adjust the index to start printing portions of the string - // - SetUnicodeMem (BufferedString, ScreenSize - 1, L' '); - PrintStringAt (Start + 1, Top + 3, BufferedString); - - if ((GetStringWidth (StringPtr) / 2) > (DimensionsWidth - 2)) { - Index = (GetStringWidth (StringPtr) / 2) - DimensionsWidth + 2; - } else { - Index = 0; - } - - if (IsPassword) { - gST->ConOut->SetCursorPosition (gST->ConOut, Start + 1, Top + 3); - } - - for (Count = 0; Index + 1 < GetStringWidth (StringPtr) / 2; Index++, Count++) { - BufferedString[Count] = StringPtr[Index]; - - if (IsPassword) { - PrintCharAt ((UINTN)-1, (UINTN)-1, L'*'); - } - } - - if (!IsPassword) { - PrintStringAt (Start + 1, Top + 3, BufferedString); - } - break; - } - - gST->ConOut->SetAttribute (gST->ConOut, EFI_TEXT_ATTR (EFI_LIGHTGRAY, EFI_BLACK)); - gST->ConOut->SetCursorPosition (gST->ConOut, Start + CurrentCursor + 1, Top + 3); - } while (TRUE); - -} - -/** - Adjust the value to the correct one. Rules follow the sample: - like: Year change: 2012.02.29 -> 2013.02.29 -> 2013.02.01 - Month change: 2013.03.29 -> 2013.02.29 -> 2013.02.28 - - @param QuestionValue Pointer to current question. - @param Sequence The sequence of the field in the question. -**/ -VOID -AdjustQuestionValue ( - IN EFI_HII_VALUE *QuestionValue, - IN UINT8 Sequence - ) -{ - UINT8 Month; - UINT16 Year; - UINT8 Maximum; - UINT8 Minimum; - - Month = QuestionValue->Value.date.Month; - Year = QuestionValue->Value.date.Year; - Minimum = 1; - - switch (Month) { - case 2: - if ((Year % 4) == 0 && ((Year % 100) != 0 || (Year % 400) == 0)) { - Maximum = 29; - } else { - Maximum = 28; - } - break; - case 4: - case 6: - case 9: - case 11: - Maximum = 30; - break; - default: - Maximum = 31; - break; - } - - // - // Change the month area. - // - if (Sequence == 0) { - if (QuestionValue->Value.date.Day > Maximum) { - QuestionValue->Value.date.Day = Maximum; - } - } - - // - // Change the Year area. - // - if (Sequence == 2) { - if (QuestionValue->Value.date.Day > Maximum) { - QuestionValue->Value.date.Day = Minimum; - } - } -} - -/** - Get field info from numeric opcode. - - @param OpCode Pointer to the current input opcode. - @param Minimum The minimum size info for this opcode. - @param Maximum The maximum size info for this opcode. - @param Step The step size info for this opcode. - @param StorageWidth The storage width info for this opcode. - -**/ -VOID -GetValueFromNum ( - IN EFI_IFR_OP_HEADER *OpCode, - OUT UINT64 *Minimum, - OUT UINT64 *Maximum, - OUT UINT64 *Step, - OUT UINT16 *StorageWidth -) -{ - EFI_IFR_NUMERIC *NumericOp; - - NumericOp = (EFI_IFR_NUMERIC *) OpCode; - - switch (NumericOp->Flags & EFI_IFR_NUMERIC_SIZE) { - case EFI_IFR_NUMERIC_SIZE_1: - *Minimum = NumericOp->data.u8.MinValue; - *Maximum = NumericOp->data.u8.MaxValue; - *Step = NumericOp->data.u8.Step; - *StorageWidth = (UINT16) sizeof (UINT8); - break; - - case EFI_IFR_NUMERIC_SIZE_2: - *Minimum = NumericOp->data.u16.MinValue; - *Maximum = NumericOp->data.u16.MaxValue; - *Step = NumericOp->data.u16.Step; - *StorageWidth = (UINT16) sizeof (UINT16); - break; - - case EFI_IFR_NUMERIC_SIZE_4: - *Minimum = NumericOp->data.u32.MinValue; - *Maximum = NumericOp->data.u32.MaxValue; - *Step = NumericOp->data.u32.Step; - *StorageWidth = (UINT16) sizeof (UINT32); - break; - - case EFI_IFR_NUMERIC_SIZE_8: - *Minimum = NumericOp->data.u64.MinValue; - *Maximum = NumericOp->data.u64.MaxValue; - *Step = NumericOp->data.u64.Step; - *StorageWidth = (UINT16) sizeof (UINT64); - break; - - default: - break; - } - - if (*Maximum == 0) { - *Maximum = (UINT64) -1; - } -} - -/** - This routine reads a numeric value from the user input. - - @param MenuOption Pointer to the current input menu. - - @retval EFI_SUCCESS If numerical input is read successfully - @retval EFI_DEVICE_ERROR If operation fails - -**/ -EFI_STATUS -GetNumericInput ( - IN UI_MENU_OPTION *MenuOption - ) -{ - EFI_STATUS Status; - UINTN Column; - UINTN Row; - CHAR16 InputText[MAX_NUMERIC_INPUT_WIDTH]; - CHAR16 FormattedNumber[MAX_NUMERIC_INPUT_WIDTH - 1]; - UINT64 PreviousNumber[MAX_NUMERIC_INPUT_WIDTH - 3]; - UINTN Count; - UINTN Loop; - BOOLEAN ManualInput; - BOOLEAN HexInput; - BOOLEAN DateOrTime; - UINTN InputWidth; - UINT64 EditValue; - UINT64 Step; - UINT64 Minimum; - UINT64 Maximum; - UINTN EraseLen; - UINT8 Digital; - EFI_INPUT_KEY Key; - EFI_HII_VALUE *QuestionValue; - FORM_DISPLAY_ENGINE_STATEMENT *Question; - EFI_IFR_NUMERIC *NumericOp; - UINT16 StorageWidth; - - Column = MenuOption->OptCol; - Row = MenuOption->Row; - PreviousNumber[0] = 0; - Count = 0; - InputWidth = 0; - Digital = 0; - StorageWidth = 0; - Minimum = 0; - Maximum = 0; - NumericOp = NULL; - - Question = MenuOption->ThisTag; - QuestionValue = &Question->CurrentValue; - - // - // Only two case, user can enter to this function: Enter and +/- case. - // In Enter case, gDirection = 0; in +/- case, gDirection = SCAN_LEFT/SCAN_WRIGHT - // - ManualInput = (BOOLEAN)(gDirection == 0 ? TRUE : FALSE); - - if ((Question->OpCode->OpCode == EFI_IFR_DATE_OP) || (Question->OpCode->OpCode == EFI_IFR_TIME_OP)) { - DateOrTime = TRUE; - } else { - DateOrTime = FALSE; - } - - // - // Prepare Value to be edit - // - EraseLen = 0; - EditValue = 0; - if (Question->OpCode->OpCode == EFI_IFR_DATE_OP) { - Step = 1; - Minimum = 1; - - switch (MenuOption->Sequence) { - case 0: - Maximum = 12; - EraseLen = 4; - EditValue = QuestionValue->Value.date.Month; - break; - - case 1: - switch (QuestionValue->Value.date.Month) { - case 2: - if ((QuestionValue->Value.date.Year % 4) == 0 && - ((QuestionValue->Value.date.Year % 100) != 0 || - (QuestionValue->Value.date.Year % 400) == 0)) { - Maximum = 29; - } else { - Maximum = 28; - } - break; - case 4: - case 6: - case 9: - case 11: - Maximum = 30; - break; - default: - Maximum = 31; - break; - } - - EraseLen = 3; - EditValue = QuestionValue->Value.date.Day; - break; - - case 2: - Maximum = 0xffff; - EraseLen = 5; - EditValue = QuestionValue->Value.date.Year; - break; - - default: - break; - } - } else if (Question->OpCode->OpCode == EFI_IFR_TIME_OP) { - Step = 1; - Minimum = 0; - - switch (MenuOption->Sequence) { - case 0: - Maximum = 23; - EraseLen = 4; - EditValue = QuestionValue->Value.time.Hour; - break; - - case 1: - Maximum = 59; - EraseLen = 3; - EditValue = QuestionValue->Value.time.Minute; - break; - - case 2: - Maximum = 59; - EraseLen = 3; - EditValue = QuestionValue->Value.time.Second; - break; - - default: - break; - } - } else { - ASSERT (Question->OpCode->OpCode == EFI_IFR_NUMERIC_OP); - NumericOp = (EFI_IFR_NUMERIC *) Question->OpCode; - GetValueFromNum(Question->OpCode, &Minimum, &Maximum, &Step, &StorageWidth); - EditValue = QuestionValue->Value.u64; - EraseLen = gOptionBlockWidth; - } - - if ((Question->OpCode->OpCode == EFI_IFR_NUMERIC_OP) && (NumericOp != NULL) && - ((NumericOp->Flags & EFI_IFR_DISPLAY) == EFI_IFR_DISPLAY_UINT_HEX)) { - HexInput = TRUE; - } else { - HexInput = FALSE; - } - - // - // Enter from "Enter" input, clear the old word showing. - // - if (ManualInput) { - if (Question->OpCode->OpCode == EFI_IFR_NUMERIC_OP) { - if (HexInput) { - InputWidth = StorageWidth * 2; - } else { - switch (StorageWidth) { - case 1: - InputWidth = 3; - break; - - case 2: - InputWidth = 5; - break; - - case 4: - InputWidth = 10; - break; - - case 8: - InputWidth = 20; - break; - - default: - InputWidth = 0; - break; - } - } - - InputText[0] = LEFT_NUMERIC_DELIMITER; - SetUnicodeMem (InputText + 1, InputWidth, L' '); - ASSERT (InputWidth + 2 < MAX_NUMERIC_INPUT_WIDTH); - InputText[InputWidth + 1] = RIGHT_NUMERIC_DELIMITER; - InputText[InputWidth + 2] = L'\0'; - - PrintStringAt (Column, Row, InputText); - Column++; - } - - if (Question->OpCode->OpCode == EFI_IFR_DATE_OP) { - if (MenuOption->Sequence == 2) { - InputWidth = 4; - } else { - InputWidth = 2; - } - - if (MenuOption->Sequence == 0) { - InputText[0] = LEFT_NUMERIC_DELIMITER; - SetUnicodeMem (InputText + 1, InputWidth, L' '); - } else { - SetUnicodeMem (InputText, InputWidth, L' '); - } - - if (MenuOption->Sequence == 2) { - InputText[InputWidth + 1] = RIGHT_NUMERIC_DELIMITER; - } else { - InputText[InputWidth + 1] = DATE_SEPARATOR; - } - InputText[InputWidth + 2] = L'\0'; - - PrintStringAt (Column, Row, InputText); - if (MenuOption->Sequence == 0) { - Column++; - } - } - - if (Question->OpCode->OpCode == EFI_IFR_TIME_OP) { - InputWidth = 2; - - if (MenuOption->Sequence == 0) { - InputText[0] = LEFT_NUMERIC_DELIMITER; - SetUnicodeMem (InputText + 1, InputWidth, L' '); - } else { - SetUnicodeMem (InputText, InputWidth, L' '); - } - - if (MenuOption->Sequence == 2) { - InputText[InputWidth + 1] = RIGHT_NUMERIC_DELIMITER; - } else { - InputText[InputWidth + 1] = TIME_SEPARATOR; - } - InputText[InputWidth + 2] = L'\0'; - - PrintStringAt (Column, Row, InputText); - if (MenuOption->Sequence == 0) { - Column++; - } - } - } - - // - // First time we enter this handler, we need to check to see if - // we were passed an increment or decrement directive - // - do { - Key.UnicodeChar = CHAR_NULL; - if (gDirection != 0) { - Key.ScanCode = gDirection; - gDirection = 0; - goto TheKey2; - } - - Status = WaitForKeyStroke (&Key); - -TheKey2: - switch (Key.UnicodeChar) { - - case '+': - case '-': - if (Key.UnicodeChar == '+') { - Key.ScanCode = SCAN_RIGHT; - } else { - Key.ScanCode = SCAN_LEFT; - } - Key.UnicodeChar = CHAR_NULL; - goto TheKey2; - - case CHAR_NULL: - switch (Key.ScanCode) { - case SCAN_LEFT: - case SCAN_RIGHT: - if (DateOrTime && !ManualInput) { - // - // By setting this value, we will return back to the caller. - // We need to do this since an auto-refresh will destroy the adjustment - // based on what the real-time-clock is showing. So we always commit - // upon changing the value. - // - gDirection = SCAN_DOWN; - } - - if ((Step != 0) && !ManualInput) { - if (Key.ScanCode == SCAN_LEFT) { - if (EditValue >= Minimum + Step) { - EditValue = EditValue - Step; - } else if (EditValue > Minimum){ - EditValue = Minimum; - } else { - EditValue = Maximum; - } - } else if (Key.ScanCode == SCAN_RIGHT) { - if (EditValue + Step <= Maximum) { - EditValue = EditValue + Step; - } else if (EditValue < Maximum) { - EditValue = Maximum; - } else { - EditValue = Minimum; - } - } - - ZeroMem (FormattedNumber, 21 * sizeof (CHAR16)); - if (Question->OpCode->OpCode == EFI_IFR_DATE_OP) { - if (MenuOption->Sequence == 2) { - // - // Year - // - UnicodeSPrint (FormattedNumber, 21 * sizeof (CHAR16), L"%04d", (UINT16) EditValue); - } else { - // - // Month/Day - // - UnicodeSPrint (FormattedNumber, 21 * sizeof (CHAR16), L"%02d", (UINT8) EditValue); - } - - if (MenuOption->Sequence == 0) { - ASSERT (EraseLen >= 2); - FormattedNumber[EraseLen - 2] = DATE_SEPARATOR; - } else if (MenuOption->Sequence == 1) { - ASSERT (EraseLen >= 1); - FormattedNumber[EraseLen - 1] = DATE_SEPARATOR; - } - } else if (Question->OpCode->OpCode == EFI_IFR_TIME_OP) { - UnicodeSPrint (FormattedNumber, 21 * sizeof (CHAR16), L"%02d", (UINT8) EditValue); - - if (MenuOption->Sequence == 0) { - ASSERT (EraseLen >= 2); - FormattedNumber[EraseLen - 2] = TIME_SEPARATOR; - } else if (MenuOption->Sequence == 1) { - ASSERT (EraseLen >= 1); - FormattedNumber[EraseLen - 1] = TIME_SEPARATOR; - } - } else { - QuestionValue->Value.u64 = EditValue; - PrintFormattedNumber (Question, FormattedNumber, 21 * sizeof (CHAR16)); - } - - gST->ConOut->SetAttribute (gST->ConOut, GetFieldTextColor ()); - for (Loop = 0; Loop < EraseLen; Loop++) { - PrintStringAt (MenuOption->OptCol + Loop, MenuOption->Row, L" "); - } - gST->ConOut->SetAttribute (gST->ConOut, GetHighlightTextColor ()); - - if (MenuOption->Sequence == 0) { - PrintCharAt (MenuOption->OptCol, Row, LEFT_NUMERIC_DELIMITER); - Column = MenuOption->OptCol + 1; - } - - PrintStringAt (Column, Row, FormattedNumber); - - if (!DateOrTime || MenuOption->Sequence == 2) { - PrintCharAt ((UINTN)-1, (UINTN)-1, RIGHT_NUMERIC_DELIMITER); - } - } - - goto EnterCarriageReturn; - break; - - case SCAN_UP: - case SCAN_DOWN: - goto EnterCarriageReturn; - - case SCAN_ESC: - return EFI_DEVICE_ERROR; - - default: - break; - } - - break; - -EnterCarriageReturn: - - case CHAR_CARRIAGE_RETURN: - // - // Validate input value with Minimum value. - // - if (EditValue < Minimum) { - UpdateStatusBar (INPUT_ERROR, TRUE); - break; - } else { - UpdateStatusBar (INPUT_ERROR, FALSE); - } - - CopyMem (&gUserInput->InputValue, &Question->CurrentValue, sizeof (EFI_HII_VALUE)); - QuestionValue = &gUserInput->InputValue; - // - // Store Edit value back to Question - // - if (Question->OpCode->OpCode == EFI_IFR_DATE_OP) { - switch (MenuOption->Sequence) { - case 0: - QuestionValue->Value.date.Month = (UINT8) EditValue; - break; - - case 1: - QuestionValue->Value.date.Day = (UINT8) EditValue; - break; - - case 2: - QuestionValue->Value.date.Year = (UINT16) EditValue; - break; - - default: - break; - } - } else if (Question->OpCode->OpCode == EFI_IFR_TIME_OP) { - switch (MenuOption->Sequence) { - case 0: - QuestionValue->Value.time.Hour = (UINT8) EditValue; - break; - - case 1: - QuestionValue->Value.time.Minute = (UINT8) EditValue; - break; - - case 2: - QuestionValue->Value.time.Second = (UINT8) EditValue; - break; - - default: - break; - } - } else { - // - // Numeric - // - QuestionValue->Value.u64 = EditValue; - } - - // - // Adjust the value to the correct one. - // Sample like: 2012.02.29 -> 2013.02.29 -> 2013.02.01 - // 2013.03.29 -> 2013.02.29 -> 2013.02.28 - // - if (Question->OpCode->OpCode == EFI_IFR_DATE_OP && - (MenuOption->Sequence == 0 || MenuOption->Sequence == 2)) { - AdjustQuestionValue (QuestionValue, (UINT8)MenuOption->Sequence); - } - - return ValidateQuestion (Question); - break; - - case CHAR_BACKSPACE: - if (ManualInput) { - if (Count == 0) { - break; - } - // - // Remove a character - // - EditValue = PreviousNumber[Count - 1]; - UpdateStatusBar (INPUT_ERROR, FALSE); - Count--; - Column--; - PrintStringAt (Column, Row, L" "); - } - break; - - default: - if (ManualInput) { - if (HexInput) { - if ((Key.UnicodeChar >= L'0') && (Key.UnicodeChar <= L'9')) { - Digital = (UINT8) (Key.UnicodeChar - L'0'); - } else if ((Key.UnicodeChar >= L'A') && (Key.UnicodeChar <= L'F')) { - Digital = (UINT8) (Key.UnicodeChar - L'A' + 0x0A); - } else if ((Key.UnicodeChar >= L'a') && (Key.UnicodeChar <= L'f')) { - Digital = (UINT8) (Key.UnicodeChar - L'a' + 0x0A); - } else { - UpdateStatusBar (INPUT_ERROR, TRUE); - break; - } - } else { - if (Key.UnicodeChar > L'9' || Key.UnicodeChar < L'0') { - UpdateStatusBar (INPUT_ERROR, TRUE); - break; - } - } - - // - // If Count exceed input width, there is no way more is valid - // - if (Count >= InputWidth) { - break; - } - // - // Someone typed something valid! - // - if (Count != 0) { - if (HexInput) { - EditValue = LShiftU64 (EditValue, 4) + Digital; - } else { - EditValue = MultU64x32 (EditValue, 10) + (Key.UnicodeChar - L'0'); - } - } else { - if (HexInput) { - EditValue = Digital; - } else { - EditValue = Key.UnicodeChar - L'0'; - } - } - - if (EditValue > Maximum) { - UpdateStatusBar (INPUT_ERROR, TRUE); - ASSERT (Count < sizeof (PreviousNumber) / sizeof (PreviousNumber[0])); - EditValue = PreviousNumber[Count]; - break; - } else { - UpdateStatusBar (INPUT_ERROR, FALSE); - } - - Count++; - ASSERT (Count < (sizeof (PreviousNumber) / sizeof (PreviousNumber[0]))); - PreviousNumber[Count] = EditValue; - - gST->ConOut->SetAttribute (gST->ConOut, GetHighlightTextColor ()); - PrintCharAt (Column, Row, Key.UnicodeChar); - Column++; - } - break; - } - } while (TRUE); -} - -/** - Adjust option order base on the question value. - - @param Question Pointer to current question. - @param PopUpMenuLines The line number of the pop up menu. - - @retval EFI_SUCCESS If Option input is processed successfully - @retval EFI_DEVICE_ERROR If operation fails - -**/ -EFI_STATUS -AdjustOptionOrder ( - IN FORM_DISPLAY_ENGINE_STATEMENT *Question, - OUT UINTN *PopUpMenuLines - ) -{ - UINTN Index; - EFI_IFR_ORDERED_LIST *OrderList; - UINT8 *ValueArray; - UINT8 ValueType; - LIST_ENTRY *Link; - DISPLAY_QUESTION_OPTION *OneOfOption; - EFI_HII_VALUE *HiiValueArray; - - Link = GetFirstNode (&Question->OptionListHead); - OneOfOption = DISPLAY_QUESTION_OPTION_FROM_LINK (Link); - ValueArray = Question->CurrentValue.Buffer; - ValueType = OneOfOption->OptionOpCode->Type; - OrderList = (EFI_IFR_ORDERED_LIST *) Question->OpCode; - - for (Index = 0; Index < OrderList->MaxContainers; Index++) { - if (GetArrayData (ValueArray, ValueType, Index) == 0) { - break; - } - } - - *PopUpMenuLines = Index; - - // - // Prepare HiiValue array - // - HiiValueArray = AllocateZeroPool (*PopUpMenuLines * sizeof (EFI_HII_VALUE)); - ASSERT (HiiValueArray != NULL); - - for (Index = 0; Index < *PopUpMenuLines; Index++) { - HiiValueArray[Index].Type = ValueType; - HiiValueArray[Index].Value.u64 = GetArrayData (ValueArray, ValueType, Index); - } - - for (Index = 0; Index < *PopUpMenuLines; Index++) { - OneOfOption = ValueToOption (Question, &HiiValueArray[*PopUpMenuLines - Index - 1]); - if (OneOfOption == NULL) { - return EFI_NOT_FOUND; - } - - RemoveEntryList (&OneOfOption->Link); - - // - // Insert to head. - // - InsertHeadList (&Question->OptionListHead, &OneOfOption->Link); - } - - FreePool (HiiValueArray); - - return EFI_SUCCESS; -} - -/** - Base on the type to compare the value. - - @param Value1 The first value need to compare. - @param Value2 The second value need to compare. - @param Type The value type for above two values. - - @retval TRUE The two value are same. - @retval FALSE The two value are different. - -**/ -BOOLEAN -IsValuesEqual ( - IN EFI_IFR_TYPE_VALUE *Value1, - IN EFI_IFR_TYPE_VALUE *Value2, - IN UINT8 Type - ) -{ - switch (Type) { - case EFI_IFR_TYPE_BOOLEAN: - case EFI_IFR_TYPE_NUM_SIZE_8: - return (BOOLEAN) (Value1->u8 == Value2->u8); - - case EFI_IFR_TYPE_NUM_SIZE_16: - return (BOOLEAN) (Value1->u16 == Value2->u16); - - case EFI_IFR_TYPE_NUM_SIZE_32: - return (BOOLEAN) (Value1->u32 == Value2->u32); - - case EFI_IFR_TYPE_NUM_SIZE_64: - return (BOOLEAN) (Value1->u64 == Value2->u64); - - default: - ASSERT (FALSE); - return FALSE; - } -} - -/** - Base on the type to set the value. - - @param Dest The dest value. - @param Source The source value. - @param Type The value type for above two values. - -**/ -VOID -SetValuesByType ( - OUT EFI_IFR_TYPE_VALUE *Dest, - IN EFI_IFR_TYPE_VALUE *Source, - IN UINT8 Type - ) -{ - switch (Type) { - case EFI_IFR_TYPE_BOOLEAN: - Dest->b = Source->b; - break; - - case EFI_IFR_TYPE_NUM_SIZE_8: - Dest->u8 = Source->u8; - break; - - case EFI_IFR_TYPE_NUM_SIZE_16: - Dest->u16 = Source->u16; - break; - - case EFI_IFR_TYPE_NUM_SIZE_32: - Dest->u32 = Source->u32; - break; - - case EFI_IFR_TYPE_NUM_SIZE_64: - Dest->u64 = Source->u64; - break; - - default: - ASSERT (FALSE); - break; - } -} - -/** - Get selection for OneOf and OrderedList (Left/Right will be ignored). - - @param MenuOption Pointer to the current input menu. - - @retval EFI_SUCCESS If Option input is processed successfully - @retval EFI_DEVICE_ERROR If operation fails - -**/ -EFI_STATUS -GetSelectionInputPopUp ( - IN UI_MENU_OPTION *MenuOption - ) -{ - EFI_STATUS Status; - EFI_INPUT_KEY Key; - UINTN Index; - CHAR16 *StringPtr; - CHAR16 *TempStringPtr; - UINTN Index2; - UINTN TopOptionIndex; - UINTN HighlightOptionIndex; - UINTN Start; - UINTN End; - UINTN Top; - UINTN Bottom; - UINTN PopUpMenuLines; - UINTN MenuLinesInView; - UINTN PopUpWidth; - CHAR16 Character; - INT32 SavedAttribute; - BOOLEAN ShowDownArrow; - BOOLEAN ShowUpArrow; - UINTN DimensionsWidth; - LIST_ENTRY *Link; - BOOLEAN OrderedList; - UINT8 *ValueArray; - UINT8 *ReturnValue; - UINT8 ValueType; - EFI_HII_VALUE HiiValue; - DISPLAY_QUESTION_OPTION *OneOfOption; - DISPLAY_QUESTION_OPTION *CurrentOption; - FORM_DISPLAY_ENGINE_STATEMENT *Question; - INTN Result; - EFI_IFR_ORDERED_LIST *OrderList; - - DimensionsWidth = gStatementDimensions.RightColumn - gStatementDimensions.LeftColumn; - - ValueArray = NULL; - ValueType = 0; - CurrentOption = NULL; - ShowDownArrow = FALSE; - ShowUpArrow = FALSE; - - StringPtr = AllocateZeroPool ((gOptionBlockWidth + 1) * 2); - ASSERT (StringPtr); - - ZeroMem (&HiiValue, sizeof (EFI_HII_VALUE)); - - Question = MenuOption->ThisTag; - if (Question->OpCode->OpCode == EFI_IFR_ORDERED_LIST_OP) { - Link = GetFirstNode (&Question->OptionListHead); - OneOfOption = DISPLAY_QUESTION_OPTION_FROM_LINK (Link); - ValueArray = Question->CurrentValue.Buffer; - ValueType = OneOfOption->OptionOpCode->Type; - OrderedList = TRUE; - OrderList = (EFI_IFR_ORDERED_LIST *) Question->OpCode; - } else { - OrderedList = FALSE; - OrderList = NULL; - } - - // - // Calculate Option count - // - PopUpMenuLines = 0; - if (OrderedList) { - AdjustOptionOrder(Question, &PopUpMenuLines); - } else { - Link = GetFirstNode (&Question->OptionListHead); - while (!IsNull (&Question->OptionListHead, Link)) { - OneOfOption = DISPLAY_QUESTION_OPTION_FROM_LINK (Link); - PopUpMenuLines++; - Link = GetNextNode (&Question->OptionListHead, Link); - } - } - - // - // Get the number of one of options present and its size - // - PopUpWidth = 0; - HighlightOptionIndex = 0; - Link = GetFirstNode (&Question->OptionListHead); - for (Index = 0; Index < PopUpMenuLines; Index++) { - OneOfOption = DISPLAY_QUESTION_OPTION_FROM_LINK (Link); - - StringPtr = GetToken (OneOfOption->OptionOpCode->Option, gFormData->HiiHandle); - if (StrLen (StringPtr) > PopUpWidth) { - PopUpWidth = StrLen (StringPtr); - } - FreePool (StringPtr); - HiiValue.Type = OneOfOption->OptionOpCode->Type; - SetValuesByType (&HiiValue.Value, &OneOfOption->OptionOpCode->Value, HiiValue.Type); - if (!OrderedList && (CompareHiiValue (&Question->CurrentValue, &HiiValue, &Result, NULL) == EFI_SUCCESS) && (Result == 0)) { - // - // Find current selected Option for OneOf - // - HighlightOptionIndex = Index; - } - - Link = GetNextNode (&Question->OptionListHead, Link); - } - - // - // Perform popup menu initialization. - // - PopUpWidth = PopUpWidth + POPUP_PAD_SPACE_COUNT; - - SavedAttribute = gST->ConOut->Mode->Attribute; - gST->ConOut->SetAttribute (gST->ConOut, GetPopupColor ()); - - if ((PopUpWidth + POPUP_FRAME_WIDTH) > DimensionsWidth) { - PopUpWidth = DimensionsWidth - POPUP_FRAME_WIDTH; - } - - Start = (DimensionsWidth - PopUpWidth - POPUP_FRAME_WIDTH) / 2 + gStatementDimensions.LeftColumn; - End = Start + PopUpWidth + POPUP_FRAME_WIDTH; - Top = gStatementDimensions.TopRow; - Bottom = gStatementDimensions.BottomRow - 1; - - MenuLinesInView = Bottom - Top - 1; - if (MenuLinesInView >= PopUpMenuLines) { - Top = Top + (MenuLinesInView - PopUpMenuLines) / 2; - Bottom = Top + PopUpMenuLines + 1; - } else { - ShowDownArrow = TRUE; - } - - if (HighlightOptionIndex > (MenuLinesInView - 1)) { - TopOptionIndex = HighlightOptionIndex - MenuLinesInView + 1; - } else { - TopOptionIndex = 0; - } - - do { - // - // Clear that portion of the screen - // - ClearLines (Start, End, Top, Bottom, GetPopupColor ()); - - // - // Draw "One of" pop-up menu - // - Character = BOXDRAW_DOWN_RIGHT; - PrintCharAt (Start, Top, Character); - for (Index = Start; Index + 2 < End; Index++) { - if ((ShowUpArrow) && ((Index + 1) == (Start + End) / 2)) { - Character = GEOMETRICSHAPE_UP_TRIANGLE; - } else { - Character = BOXDRAW_HORIZONTAL; - } - - PrintCharAt ((UINTN)-1, (UINTN)-1, Character); - } - - Character = BOXDRAW_DOWN_LEFT; - PrintCharAt ((UINTN)-1, (UINTN)-1, Character); - Character = BOXDRAW_VERTICAL; - for (Index = Top + 1; Index < Bottom; Index++) { - PrintCharAt (Start, Index, Character); - PrintCharAt (End - 1, Index, Character); - } - - // - // Move to top Option - // - Link = GetFirstNode (&Question->OptionListHead); - for (Index = 0; Index < TopOptionIndex; Index++) { - Link = GetNextNode (&Question->OptionListHead, Link); - } - - // - // Display the One of options - // - Index2 = Top + 1; - for (Index = TopOptionIndex; (Index < PopUpMenuLines) && (Index2 < Bottom); Index++) { - OneOfOption = DISPLAY_QUESTION_OPTION_FROM_LINK (Link); - Link = GetNextNode (&Question->OptionListHead, Link); - - StringPtr = GetToken (OneOfOption->OptionOpCode->Option, gFormData->HiiHandle); - ASSERT (StringPtr != NULL); - // - // If the string occupies multiple lines, truncate it to fit in one line, - // and append a "..." for indication. - // - if (StrLen (StringPtr) > (PopUpWidth - 1)) { - TempStringPtr = AllocateZeroPool (sizeof (CHAR16) * (PopUpWidth - 1)); - ASSERT ( TempStringPtr != NULL ); - CopyMem (TempStringPtr, StringPtr, (sizeof (CHAR16) * (PopUpWidth - 5))); - FreePool (StringPtr); - StringPtr = TempStringPtr; - StrCat (StringPtr, L"..."); - } - - if (Index == HighlightOptionIndex) { - // - // Highlight the selected one - // - CurrentOption = OneOfOption; - - gST->ConOut->SetAttribute (gST->ConOut, GetPickListColor ()); - PrintStringAt (Start + 2, Index2, StringPtr); - gST->ConOut->SetAttribute (gST->ConOut, GetPopupColor ()); - } else { - gST->ConOut->SetAttribute (gST->ConOut, GetPopupColor ()); - PrintStringAt (Start + 2, Index2, StringPtr); - } - - Index2++; - FreePool (StringPtr); - } - - Character = BOXDRAW_UP_RIGHT; - PrintCharAt (Start, Bottom, Character); - for (Index = Start; Index + 2 < End; Index++) { - if ((ShowDownArrow) && ((Index + 1) == (Start + End) / 2)) { - Character = GEOMETRICSHAPE_DOWN_TRIANGLE; - } else { - Character = BOXDRAW_HORIZONTAL; - } - - PrintCharAt ((UINTN)-1, (UINTN)-1, Character); - } - - Character = BOXDRAW_UP_LEFT; - PrintCharAt ((UINTN)-1, (UINTN)-1, Character); - - // - // Get User selection - // - Key.UnicodeChar = CHAR_NULL; - if ((gDirection == SCAN_UP) || (gDirection == SCAN_DOWN)) { - Key.ScanCode = gDirection; - gDirection = 0; - goto TheKey; - } - - Status = WaitForKeyStroke (&Key); - -TheKey: - switch (Key.UnicodeChar) { - case '+': - if (OrderedList) { - if ((TopOptionIndex > 0) && (TopOptionIndex == HighlightOptionIndex)) { - // - // Highlight reaches the top of the popup window, scroll one menu item. - // - TopOptionIndex--; - ShowDownArrow = TRUE; - } - - if (TopOptionIndex == 0) { - ShowUpArrow = FALSE; - } - - if (HighlightOptionIndex > 0) { - HighlightOptionIndex--; - - ASSERT (CurrentOption != NULL); - SwapListEntries (CurrentOption->Link.BackLink, &CurrentOption->Link); - } - } - break; - - case '-': - // - // If an ordered list op-code, we will allow for a popup of +/- keys - // to create an ordered list of items - // - if (OrderedList) { - if (((TopOptionIndex + MenuLinesInView) < PopUpMenuLines) && - (HighlightOptionIndex == (TopOptionIndex + MenuLinesInView - 1))) { - // - // Highlight reaches the bottom of the popup window, scroll one menu item. - // - TopOptionIndex++; - ShowUpArrow = TRUE; - } - - if ((TopOptionIndex + MenuLinesInView) == PopUpMenuLines) { - ShowDownArrow = FALSE; - } - - if (HighlightOptionIndex < (PopUpMenuLines - 1)) { - HighlightOptionIndex++; - - ASSERT (CurrentOption != NULL); - SwapListEntries (&CurrentOption->Link, CurrentOption->Link.ForwardLink); - } - } - break; - - case CHAR_NULL: - switch (Key.ScanCode) { - case SCAN_UP: - case SCAN_DOWN: - if (Key.ScanCode == SCAN_UP) { - if ((TopOptionIndex > 0) && (TopOptionIndex == HighlightOptionIndex)) { - // - // Highlight reaches the top of the popup window, scroll one menu item. - // - TopOptionIndex--; - ShowDownArrow = TRUE; - } - - if (TopOptionIndex == 0) { - ShowUpArrow = FALSE; - } - - if (HighlightOptionIndex > 0) { - HighlightOptionIndex--; - } - } else { - if (((TopOptionIndex + MenuLinesInView) < PopUpMenuLines) && - (HighlightOptionIndex == (TopOptionIndex + MenuLinesInView - 1))) { - // - // Highlight reaches the bottom of the popup window, scroll one menu item. - // - TopOptionIndex++; - ShowUpArrow = TRUE; - } - - if ((TopOptionIndex + MenuLinesInView) == PopUpMenuLines) { - ShowDownArrow = FALSE; - } - - if (HighlightOptionIndex < (PopUpMenuLines - 1)) { - HighlightOptionIndex++; - } - } - break; - - case SCAN_ESC: - gST->ConOut->SetAttribute (gST->ConOut, SavedAttribute); - - // - // Restore link list order for orderedlist - // - if (OrderedList) { - HiiValue.Type = ValueType; - HiiValue.Value.u64 = 0; - for (Index = 0; Index < OrderList->MaxContainers; Index++) { - HiiValue.Value.u64 = GetArrayData (ValueArray, ValueType, Index); - if (HiiValue.Value.u64 == 0) { - break; - } - - OneOfOption = ValueToOption (Question, &HiiValue); - if (OneOfOption == NULL) { - return EFI_NOT_FOUND; - } - - RemoveEntryList (&OneOfOption->Link); - InsertTailList (&Question->OptionListHead, &OneOfOption->Link); - } - } - - return EFI_DEVICE_ERROR; - - default: - break; - } - - break; - - case CHAR_CARRIAGE_RETURN: - // - // return the current selection - // - if (OrderedList) { - ReturnValue = AllocateZeroPool (Question->CurrentValue.BufferLen); - ASSERT (ReturnValue != NULL); - Index = 0; - Link = GetFirstNode (&Question->OptionListHead); - while (!IsNull (&Question->OptionListHead, Link)) { - OneOfOption = DISPLAY_QUESTION_OPTION_FROM_LINK (Link); - Link = GetNextNode (&Question->OptionListHead, Link); - - SetArrayData (ReturnValue, ValueType, Index, OneOfOption->OptionOpCode->Value.u64); - - Index++; - if (Index > OrderList->MaxContainers) { - break; - } - } - if (CompareMem (ReturnValue, ValueArray, Question->CurrentValue.BufferLen) == 0) { - FreePool (ReturnValue); - return EFI_DEVICE_ERROR; - } else { - gUserInput->InputValue.Buffer = ReturnValue; - gUserInput->InputValue.BufferLen = Question->CurrentValue.BufferLen; - Status = EFI_SUCCESS; - } - } else { - ASSERT (CurrentOption != NULL); - gUserInput->InputValue.Type = CurrentOption->OptionOpCode->Type; - if (IsValuesEqual (&Question->CurrentValue.Value, &CurrentOption->OptionOpCode->Value, gUserInput->InputValue.Type)) { - return EFI_DEVICE_ERROR; - } else { - SetValuesByType (&gUserInput->InputValue.Value, &CurrentOption->OptionOpCode->Value, gUserInput->InputValue.Type); - Status = EFI_SUCCESS; - } - } - - gST->ConOut->SetAttribute (gST->ConOut, SavedAttribute); - - return ValidateQuestion (Question); - - default: - break; - } - } while (TRUE); - -} - diff --git a/MdeModulePkg/Universal/DisplayEngineDxe/ProcessOptions.c b/MdeModulePkg/Universal/DisplayEngineDxe/ProcessOptions.c deleted file mode 100644 index aca043a8c2..0000000000 --- a/MdeModulePkg/Universal/DisplayEngineDxe/ProcessOptions.c +++ /dev/null @@ -1,1286 +0,0 @@ -/** @file -Implementation for handling the User Interface option processing. - - -Copyright (c) 2004 - 2012, Intel Corporation. All rights reserved.
-This program and the accompanying materials -are licensed and made available under the terms and conditions of the BSD License -which accompanies this distribution. The full text of the license may be found at -http://opensource.org/licenses/bsd-license.php - -THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, -WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. - -**/ - -#include "FormDisplay.h" - -/** - Concatenate a narrow string to another string. - - @param Destination The destination string. - @param Source The source string. The string to be concatenated. - to the end of Destination. - -**/ -VOID -NewStrCat ( - IN OUT CHAR16 *Destination, - IN CHAR16 *Source - ) -{ - UINTN Length; - - for (Length = 0; Destination[Length] != 0; Length++) - ; - - // - // We now have the length of the original string - // We can safely assume for now that we are concatenating a narrow value to this string. - // For instance, the string is "XYZ" and cat'ing ">" - // If this assumption changes, we need to make this routine a bit more complex - // - Destination[Length] = NARROW_CHAR; - Length++; - - StrCpy (Destination + Length, Source); -} - -/** - Compare two Hii value. - - @param Value1 Expression value to compare on left-hand. - @param Value2 Expression value to compare on right-hand. - @param Result Return value after compare. - retval 0 Two operators equal. - return Positive value if Value1 is greater than Value2. - retval Negative value if Value1 is less than Value2. - @param HiiHandle Only required for string compare. - - @retval other Could not perform compare on two values. - @retval EFI_SUCCESS Compare the value success. - -**/ -EFI_STATUS -CompareHiiValue ( - IN EFI_HII_VALUE *Value1, - IN EFI_HII_VALUE *Value2, - OUT INTN *Result, - IN EFI_HII_HANDLE HiiHandle OPTIONAL - ) -{ - INT64 Temp64; - CHAR16 *Str1; - CHAR16 *Str2; - UINTN Len; - - if (Value1->Type >= EFI_IFR_TYPE_OTHER || Value2->Type >= EFI_IFR_TYPE_OTHER ) { - if (Value1->Type != EFI_IFR_TYPE_BUFFER && Value2->Type != EFI_IFR_TYPE_BUFFER) { - return EFI_UNSUPPORTED; - } - } - - if (Value1->Type == EFI_IFR_TYPE_STRING || Value2->Type == EFI_IFR_TYPE_STRING ) { - if (Value1->Type != Value2->Type) { - // - // Both Operator should be type of String - // - return EFI_UNSUPPORTED; - } - - if (Value1->Value.string == 0 || Value2->Value.string == 0) { - // - // StringId 0 is reserved - // - return EFI_INVALID_PARAMETER; - } - - if (Value1->Value.string == Value2->Value.string) { - *Result = 0; - return EFI_SUCCESS; - } - - Str1 = GetToken (Value1->Value.string, HiiHandle); - if (Str1 == NULL) { - // - // String not found - // - return EFI_NOT_FOUND; - } - - Str2 = GetToken (Value2->Value.string, HiiHandle); - if (Str2 == NULL) { - FreePool (Str1); - return EFI_NOT_FOUND; - } - - *Result = StrCmp (Str1, Str2); - - FreePool (Str1); - FreePool (Str2); - - return EFI_SUCCESS; - } - - if (Value1->Type == EFI_IFR_TYPE_BUFFER || Value2->Type == EFI_IFR_TYPE_BUFFER ) { - if (Value1->Type != Value2->Type) { - // - // Both Operator should be type of Buffer. - // - return EFI_UNSUPPORTED; - } - Len = Value1->BufferLen > Value2->BufferLen ? Value2->BufferLen : Value1->BufferLen; - *Result = CompareMem (Value1->Buffer, Value2->Buffer, Len); - if ((*Result == 0) && (Value1->BufferLen != Value2->BufferLen)) - { - // - // In this case, means base on samll number buffer, the data is same - // So which value has more data, which value is bigger. - // - *Result = Value1->BufferLen > Value2->BufferLen ? 1 : -1; - } - return EFI_SUCCESS; - } - - // - // Take remain types(integer, boolean, date/time) as integer - // - Temp64 = (INT64) (Value1->Value.u64 - Value2->Value.u64); - if (Temp64 > 0) { - *Result = 1; - } else if (Temp64 < 0) { - *Result = -1; - } else { - *Result = 0; - } - - return EFI_SUCCESS; -} - -/** - Search an Option of a Question by its value. - - @param Question The Question - @param OptionValue Value for Option to be searched. - - @retval Pointer Pointer to the found Option. - @retval NULL Option not found. - -**/ -DISPLAY_QUESTION_OPTION * -ValueToOption ( - IN FORM_DISPLAY_ENGINE_STATEMENT *Question, - IN EFI_HII_VALUE *OptionValue - ) -{ - LIST_ENTRY *Link; - DISPLAY_QUESTION_OPTION *Option; - INTN Result; - EFI_HII_VALUE Value; - - Link = GetFirstNode (&Question->OptionListHead); - while (!IsNull (&Question->OptionListHead, Link)) { - Option = DISPLAY_QUESTION_OPTION_FROM_LINK (Link); - - ZeroMem (&Value, sizeof (EFI_HII_VALUE)); - Value.Type = Option->OptionOpCode->Type; - CopyMem (&Value.Value, &Option->OptionOpCode->Value, Option->OptionOpCode->Header.Length - OFFSET_OF (EFI_IFR_ONE_OF_OPTION, Value)); - - if ((CompareHiiValue (&Value, OptionValue, &Result, NULL) == EFI_SUCCESS) && (Result == 0)) { - return Option; - } - - Link = GetNextNode (&Question->OptionListHead, Link); - } - - return NULL; -} - - -/** - Return data element in an Array by its Index. - - @param Array The data array. - @param Type Type of the data in this array. - @param Index Zero based index for data in this array. - - @retval Value The data to be returned - -**/ -UINT64 -GetArrayData ( - IN VOID *Array, - IN UINT8 Type, - IN UINTN Index - ) -{ - UINT64 Data; - - ASSERT (Array != NULL); - - Data = 0; - switch (Type) { - case EFI_IFR_TYPE_NUM_SIZE_8: - Data = (UINT64) *(((UINT8 *) Array) + Index); - break; - - case EFI_IFR_TYPE_NUM_SIZE_16: - Data = (UINT64) *(((UINT16 *) Array) + Index); - break; - - case EFI_IFR_TYPE_NUM_SIZE_32: - Data = (UINT64) *(((UINT32 *) Array) + Index); - break; - - case EFI_IFR_TYPE_NUM_SIZE_64: - Data = (UINT64) *(((UINT64 *) Array) + Index); - break; - - default: - break; - } - - return Data; -} - - -/** - Set value of a data element in an Array by its Index. - - @param Array The data array. - @param Type Type of the data in this array. - @param Index Zero based index for data in this array. - @param Value The value to be set. - -**/ -VOID -SetArrayData ( - IN VOID *Array, - IN UINT8 Type, - IN UINTN Index, - IN UINT64 Value - ) -{ - - ASSERT (Array != NULL); - - switch (Type) { - case EFI_IFR_TYPE_NUM_SIZE_8: - *(((UINT8 *) Array) + Index) = (UINT8) Value; - break; - - case EFI_IFR_TYPE_NUM_SIZE_16: - *(((UINT16 *) Array) + Index) = (UINT16) Value; - break; - - case EFI_IFR_TYPE_NUM_SIZE_32: - *(((UINT32 *) Array) + Index) = (UINT32) Value; - break; - - case EFI_IFR_TYPE_NUM_SIZE_64: - *(((UINT64 *) Array) + Index) = (UINT64) Value; - break; - - default: - break; - } -} - -/** - Check whether this value already in the array, if yes, return the index. - - @param Array The data array. - @param Type Type of the data in this array. - @param Value The value to be find. - @param Index The index in the array which has same value with Value. - - @retval TRUE Found the value in the array. - @retval FALSE Not found the value. - -**/ -BOOLEAN -FindArrayData ( - IN VOID *Array, - IN UINT8 Type, - IN UINT64 Value, - OUT UINTN *Index OPTIONAL - ) -{ - UINTN Count; - UINT64 TmpValue; - UINT64 ValueComp; - - ASSERT (Array != NULL); - - Count = 0; - TmpValue = 0; - - switch (Type) { - case EFI_IFR_TYPE_NUM_SIZE_8: - ValueComp = (UINT8) Value; - break; - - case EFI_IFR_TYPE_NUM_SIZE_16: - ValueComp = (UINT16) Value; - break; - - case EFI_IFR_TYPE_NUM_SIZE_32: - ValueComp = (UINT32) Value; - break; - - case EFI_IFR_TYPE_NUM_SIZE_64: - ValueComp = (UINT64) Value; - break; - - default: - ValueComp = 0; - break; - } - - while ((TmpValue = GetArrayData (Array, Type, Count)) != 0) { - if (ValueComp == TmpValue) { - if (Index != NULL) { - *Index = Count; - } - return TRUE; - } - - Count ++; - } - - return FALSE; -} - -/** - Print Question Value according to it's storage width and display attributes. - - @param Question The Question to be printed. - @param FormattedNumber Buffer for output string. - @param BufferSize The FormattedNumber buffer size in bytes. - - @retval EFI_SUCCESS Print success. - @retval EFI_BUFFER_TOO_SMALL Buffer size is not enough for formatted number. - -**/ -EFI_STATUS -PrintFormattedNumber ( - IN FORM_DISPLAY_ENGINE_STATEMENT *Question, - IN OUT CHAR16 *FormattedNumber, - IN UINTN BufferSize - ) -{ - INT64 Value; - CHAR16 *Format; - EFI_HII_VALUE *QuestionValue; - EFI_IFR_NUMERIC *NumericOp; - - if (BufferSize < (21 * sizeof (CHAR16))) { - return EFI_BUFFER_TOO_SMALL; - } - - QuestionValue = &Question->CurrentValue; - NumericOp = (EFI_IFR_NUMERIC *) Question->OpCode; - - Value = (INT64) QuestionValue->Value.u64; - switch (NumericOp->Flags & EFI_IFR_DISPLAY) { - case EFI_IFR_DISPLAY_INT_DEC: - switch (QuestionValue->Type) { - case EFI_IFR_NUMERIC_SIZE_1: - Value = (INT64) ((INT8) QuestionValue->Value.u8); - break; - - case EFI_IFR_NUMERIC_SIZE_2: - Value = (INT64) ((INT16) QuestionValue->Value.u16); - break; - - case EFI_IFR_NUMERIC_SIZE_4: - Value = (INT64) ((INT32) QuestionValue->Value.u32); - break; - - case EFI_IFR_NUMERIC_SIZE_8: - default: - break; - } - - if (Value < 0) { - Value = -Value; - Format = L"-%ld"; - } else { - Format = L"%ld"; - } - break; - - case EFI_IFR_DISPLAY_UINT_DEC: - Format = L"%ld"; - break; - - case EFI_IFR_DISPLAY_UINT_HEX: - Format = L"%lx"; - break; - - default: - return EFI_UNSUPPORTED; - break; - } - - UnicodeSPrint (FormattedNumber, BufferSize, Format, Value); - - return EFI_SUCCESS; -} - - -/** - Draw a pop up windows based on the dimension, number of lines and - strings specified. - - @param RequestedWidth The width of the pop-up. - @param NumberOfLines The number of lines. - @param Marker The variable argument list for the list of string to be printed. - -**/ -VOID -CreateSharedPopUp ( - IN UINTN RequestedWidth, - IN UINTN NumberOfLines, - IN VA_LIST Marker - ) -{ - UINTN Index; - UINTN Count; - CHAR16 Character; - UINTN Start; - UINTN End; - UINTN Top; - UINTN Bottom; - CHAR16 *String; - UINTN DimensionsWidth; - UINTN DimensionsHeight; - - DimensionsWidth = gStatementDimensions.RightColumn - gStatementDimensions.LeftColumn; - DimensionsHeight = gStatementDimensions.BottomRow - gStatementDimensions.TopRow; - - gST->ConOut->SetAttribute (gST->ConOut, GetPopupColor ()); - - if ((RequestedWidth + 2) > DimensionsWidth) { - RequestedWidth = DimensionsWidth - 2; - } - - // - // Subtract the PopUp width from total Columns, allow for one space extra on - // each end plus a border. - // - Start = (DimensionsWidth - RequestedWidth - 2) / 2 + gStatementDimensions.LeftColumn + 1; - End = Start + RequestedWidth + 1; - - Top = ((DimensionsHeight - NumberOfLines - 2) / 2) + gStatementDimensions.TopRow - 1; - Bottom = Top + NumberOfLines + 2; - - Character = BOXDRAW_DOWN_RIGHT; - PrintCharAt (Start, Top, Character); - Character = BOXDRAW_HORIZONTAL; - for (Index = Start; Index + 2 < End; Index++) { - PrintCharAt ((UINTN)-1, (UINTN)-1, Character); - } - - Character = BOXDRAW_DOWN_LEFT; - PrintCharAt ((UINTN)-1, (UINTN)-1, Character); - Character = BOXDRAW_VERTICAL; - - Count = 0; - for (Index = Top; Index + 2 < Bottom; Index++, Count++) { - String = VA_ARG (Marker, CHAR16*); - - // - // This will clear the background of the line - we never know who might have been - // here before us. This differs from the next clear in that it used the non-reverse - // video for normal printing. - // - if (GetStringWidth (String) / 2 > 1) { - ClearLines (Start, End, Index + 1, Index + 1, GetPopupColor ()); - } - - // - // Passing in a space results in the assumption that this is where typing will occur - // - if (String[0] == L' ') { - ClearLines (Start + 1, End - 1, Index + 1, Index + 1, GetPopupInverseColor ()); - } - - // - // Passing in a NULL results in a blank space - // - if (String[0] == CHAR_NULL) { - ClearLines (Start, End, Index + 1, Index + 1, GetPopupColor ()); - } - - PrintStringAt ( - ((DimensionsWidth - GetStringWidth (String) / 2) / 2) + gStatementDimensions.LeftColumn + 1, - Index + 1, - String - ); - gST->ConOut->SetAttribute (gST->ConOut, GetPopupColor ()); - PrintCharAt (Start, Index + 1, Character); - PrintCharAt (End - 1, Index + 1, Character); - } - - Character = BOXDRAW_UP_RIGHT; - PrintCharAt (Start, Bottom - 1, Character); - Character = BOXDRAW_HORIZONTAL; - for (Index = Start; Index + 2 < End; Index++) { - PrintCharAt ((UINTN)-1, (UINTN)-1, Character); - } - - Character = BOXDRAW_UP_LEFT; - PrintCharAt ((UINTN)-1, (UINTN)-1, Character); -} - -/** - Draw a pop up windows based on the dimension, number of lines and - strings specified. - - @param RequestedWidth The width of the pop-up. - @param NumberOfLines The number of lines. - @param ... A series of text strings that displayed in the pop-up. - -**/ -VOID -EFIAPI -CreateMultiStringPopUp ( - IN UINTN RequestedWidth, - IN UINTN NumberOfLines, - ... - ) -{ - VA_LIST Marker; - - VA_START (Marker, NumberOfLines); - - CreateSharedPopUp (RequestedWidth, NumberOfLines, Marker); - - VA_END (Marker); -} - -/** - Process validate for one question. - - @param Question The question need to be validate. - - @retval EFI_SUCCESS Question Option process success. - @retval EFI_INVALID_PARAMETER Question Option process fail. - -**/ -EFI_STATUS -ValidateQuestion ( - IN FORM_DISPLAY_ENGINE_STATEMENT *Question - ) -{ - CHAR16 *ErrorInfo; - EFI_INPUT_KEY Key; - EFI_STATUS Status; - STATEMENT_ERROR_INFO RetInfo; - UINT32 RetVal; - - if (Question->ValidateQuestion == NULL) { - return EFI_SUCCESS; - } - - Status = EFI_SUCCESS; - RetVal = Question->ValidateQuestion(gFormData, Question, &gUserInput->InputValue, &RetInfo); - - switch (RetVal) { - case INCOSISTENT_IF_TRUE: - // - // Condition meet, show up error message - // - ASSERT (RetInfo.StringId != 0); - ErrorInfo = GetToken (RetInfo.StringId, gFormData->HiiHandle); - do { - CreateDialog (&Key, gEmptyString, ErrorInfo, gPressEnter, gEmptyString, NULL); - } while (Key.UnicodeChar != CHAR_CARRIAGE_RETURN); - FreePool (ErrorInfo); - - Status = EFI_INVALID_PARAMETER; - break; - - default: - break; - } - - return Status; -} - -/** - Display error message for invalid password. - -**/ -VOID -PasswordInvalid ( - VOID - ) -{ - EFI_INPUT_KEY Key; - - // - // Invalid password, prompt error message - // - do { - CreateDialog (&Key, gEmptyString, gPassowordInvalid, gPressEnter, gEmptyString, NULL); - } while (Key.UnicodeChar != CHAR_CARRIAGE_RETURN); -} - -/** - Process password op code. - - @param MenuOption The menu for current password op code. - - @retval EFI_SUCCESS Question Option process success. - @retval Other Question Option process fail. - -**/ -EFI_STATUS -PasswordProcess ( - IN UI_MENU_OPTION *MenuOption - ) -{ - CHAR16 *StringPtr; - CHAR16 *TempString; - UINTN Maximum; - EFI_STATUS Status; - EFI_IFR_PASSWORD *PasswordInfo; - FORM_DISPLAY_ENGINE_STATEMENT *Question; - EFI_INPUT_KEY Key; - - Question = MenuOption->ThisTag; - PasswordInfo = (EFI_IFR_PASSWORD *) Question->OpCode; - Maximum = PasswordInfo->MaxSize; - Status = EFI_SUCCESS; - - StringPtr = AllocateZeroPool ((Maximum + 1) * sizeof (CHAR16)); - ASSERT (StringPtr); - - // - // Use a NULL password to test whether old password is required - // - *StringPtr = 0; - Status = Question->PasswordCheck (gFormData, Question, StringPtr); - if (Status == EFI_NOT_AVAILABLE_YET || Status == EFI_UNSUPPORTED) { - // - // Password can't be set now. - // - FreePool (StringPtr); - return EFI_SUCCESS; - } - - if (EFI_ERROR (Status)) { - // - // Old password exist, ask user for the old password - // - Status = ReadString (MenuOption, gPromptForPassword, StringPtr); - if (EFI_ERROR (Status)) { - FreePool (StringPtr); - return Status; - } - - // - // Check user input old password - // - Status = Question->PasswordCheck (gFormData, Question, StringPtr); - if (EFI_ERROR (Status)) { - if (Status == EFI_NOT_READY) { - // - // Typed in old password incorrect - // - PasswordInvalid (); - } else { - Status = EFI_SUCCESS; - } - - FreePool (StringPtr); - return Status; - } - } - - // - // Ask for new password - // - ZeroMem (StringPtr, (Maximum + 1) * sizeof (CHAR16)); - Status = ReadString (MenuOption, gPromptForNewPassword, StringPtr); - if (EFI_ERROR (Status)) { - // - // Reset state machine for password - // - Question->PasswordCheck (gFormData, Question, NULL); - FreePool (StringPtr); - return Status; - } - - // - // Confirm new password - // - TempString = AllocateZeroPool ((Maximum + 1) * sizeof (CHAR16)); - ASSERT (TempString); - Status = ReadString (MenuOption, gConfirmPassword, TempString); - if (EFI_ERROR (Status)) { - // - // Reset state machine for password - // - Question->PasswordCheck (gFormData, Question, NULL); - FreePool (StringPtr); - FreePool (TempString); - return Status; - } - - // - // Compare two typed-in new passwords - // - if (StrCmp (StringPtr, TempString) == 0) { - gUserInput->InputValue.Buffer = AllocateCopyPool (Question->CurrentValue.BufferLen, StringPtr); - gUserInput->InputValue.BufferLen = Question->CurrentValue.BufferLen; - gUserInput->InputValue.Type = Question->CurrentValue.Type; - gUserInput->InputValue.Value.string = HiiSetString(gFormData->HiiHandle, gUserInput->InputValue.Value.string, StringPtr, NULL); - FreePool (StringPtr); - - Status = ValidateQuestion (Question); - - if (EFI_ERROR (Status)) { - // - // Reset state machine for password - // - Question->PasswordCheck (gFormData, Question, NULL); - } - - return Status; - } else { - // - // Reset state machine for password - // - Question->PasswordCheck (gFormData, Question, NULL); - - // - // Two password mismatch, prompt error message - // - do { - CreateDialog (&Key, gEmptyString, gConfirmError, gPressEnter, gEmptyString, NULL); - } while (Key.UnicodeChar != CHAR_CARRIAGE_RETURN); - - Status = EFI_INVALID_PARAMETER; - } - - FreePool (TempString); - FreePool (StringPtr); - - return Status; -} - -/** - Process a Question's Option (whether selected or un-selected). - - @param MenuOption The MenuOption for this Question. - @param Selected TRUE: if Question is selected. - @param OptionString Pointer of the Option String to be displayed. - @param SkipErrorValue Whether need to return when value without option for it. - - @retval EFI_SUCCESS Question Option process success. - @retval Other Question Option process fail. - -**/ -EFI_STATUS -ProcessOptions ( - IN UI_MENU_OPTION *MenuOption, - IN BOOLEAN Selected, - OUT CHAR16 **OptionString, - IN BOOLEAN SkipErrorValue - ) -{ - EFI_STATUS Status; - CHAR16 *StringPtr; - UINTN Index; - FORM_DISPLAY_ENGINE_STATEMENT *Question; - CHAR16 FormattedNumber[21]; - UINT16 Number; - CHAR16 Character[2]; - EFI_INPUT_KEY Key; - UINTN BufferSize; - DISPLAY_QUESTION_OPTION *OneOfOption; - LIST_ENTRY *Link; - EFI_HII_VALUE HiiValue; - EFI_HII_VALUE *QuestionValue; - DISPLAY_QUESTION_OPTION *Option; - UINTN Index2; - UINT8 *ValueArray; - UINT8 ValueType; - EFI_STRING_ID StringId; - EFI_IFR_ORDERED_LIST *OrderList; - BOOLEAN ValueInvalid; - - Status = EFI_SUCCESS; - - StringPtr = NULL; - Character[1] = L'\0'; - *OptionString = NULL; - StringId = 0; - ValueInvalid = FALSE; - - ZeroMem (FormattedNumber, 21 * sizeof (CHAR16)); - BufferSize = (gOptionBlockWidth + 1) * 2 * gStatementDimensions.BottomRow; - - Question = MenuOption->ThisTag; - QuestionValue = &Question->CurrentValue; - - switch (Question->OpCode->OpCode) { - case EFI_IFR_ORDERED_LIST_OP: - - // - // Check whether there are Options of this OrderedList - // - if (IsListEmpty (&Question->OptionListHead)) { - break; - } - - OrderList = (EFI_IFR_ORDERED_LIST *) Question->OpCode; - - Link = GetFirstNode (&Question->OptionListHead); - OneOfOption = DISPLAY_QUESTION_OPTION_FROM_LINK (Link); - - ValueType = OneOfOption->OptionOpCode->Type; - ValueArray = Question->CurrentValue.Buffer; - - if (Selected) { - // - // Go ask for input - // - Status = GetSelectionInputPopUp (MenuOption); - } else { - // - // We now know how many strings we will have, so we can allocate the - // space required for the array or strings. - // - *OptionString = AllocateZeroPool (OrderList->MaxContainers * BufferSize); - ASSERT (*OptionString); - - HiiValue.Type = ValueType; - HiiValue.Value.u64 = 0; - for (Index = 0; Index < OrderList->MaxContainers; Index++) { - HiiValue.Value.u64 = GetArrayData (ValueArray, ValueType, Index); - if (HiiValue.Value.u64 == 0) { - // - // Values for the options in ordered lists should never be a 0 - // - break; - } - - OneOfOption = ValueToOption (Question, &HiiValue); - if (OneOfOption == NULL) { - if (SkipErrorValue) { - // - // Just try to get the option string, skip the value which not has option. - // - continue; - } - - // - // Show error message - // - do { - CreateDialog (&Key, gEmptyString, gOptionMismatch, gPressEnter, gEmptyString, NULL); - } while (Key.UnicodeChar != CHAR_CARRIAGE_RETURN); - - // - // The initial value of the orderedlist is invalid, force to be valid value - // Exit current DisplayForm with new value. - // - gUserInput->SelectedStatement = Question; - - ValueArray = AllocateZeroPool (Question->CurrentValue.BufferLen); - ASSERT (ValueArray != NULL); - gUserInput->InputValue.Buffer = ValueArray; - gUserInput->InputValue.BufferLen = Question->CurrentValue.BufferLen; - gUserInput->InputValue.Type = Question->CurrentValue.Type; - - Link = GetFirstNode (&Question->OptionListHead); - Index2 = 0; - while (!IsNull (&Question->OptionListHead, Link) && Index2 < OrderList->MaxContainers) { - Option = DISPLAY_QUESTION_OPTION_FROM_LINK (Link); - Link = GetNextNode (&Question->OptionListHead, Link); - SetArrayData (ValueArray, ValueType, Index2, Option->OptionOpCode->Value.u64); - Index2++; - } - SetArrayData (ValueArray, ValueType, Index2, 0); - - FreePool (*OptionString); - *OptionString = NULL; - return EFI_NOT_FOUND; - } - - Character[0] = LEFT_ONEOF_DELIMITER; - NewStrCat (OptionString[0], Character); - StringPtr = GetToken (OneOfOption->OptionOpCode->Option, gFormData->HiiHandle); - ASSERT (StringPtr != NULL); - NewStrCat (OptionString[0], StringPtr); - Character[0] = RIGHT_ONEOF_DELIMITER; - NewStrCat (OptionString[0], Character); - Character[0] = CHAR_CARRIAGE_RETURN; - NewStrCat (OptionString[0], Character); - FreePool (StringPtr); - } - - // - // If valid option more than the max container, skip these options. - // - if (Index >= OrderList->MaxContainers) { - break; - } - - // - // Search the other options, try to find the one not in the container. - // - Link = GetFirstNode (&Question->OptionListHead); - while (!IsNull (&Question->OptionListHead, Link)) { - OneOfOption = DISPLAY_QUESTION_OPTION_FROM_LINK (Link); - Link = GetNextNode (&Question->OptionListHead, Link); - - if (FindArrayData (ValueArray, ValueType, OneOfOption->OptionOpCode->Value.u64, NULL)) { - continue; - } - - if (SkipErrorValue) { - // - // Not report error, just get the correct option string info. - // - Character[0] = LEFT_ONEOF_DELIMITER; - NewStrCat (OptionString[0], Character); - StringPtr = GetToken (OneOfOption->OptionOpCode->Option, gFormData->HiiHandle); - ASSERT (StringPtr != NULL); - NewStrCat (OptionString[0], StringPtr); - Character[0] = RIGHT_ONEOF_DELIMITER; - NewStrCat (OptionString[0], Character); - Character[0] = CHAR_CARRIAGE_RETURN; - NewStrCat (OptionString[0], Character); - FreePool (StringPtr); - - continue; - } - - if (!ValueInvalid) { - ValueInvalid = TRUE; - // - // Show error message - // - do { - CreateDialog (&Key, gEmptyString, gOptionMismatch, gPressEnter, gEmptyString, NULL); - } while (Key.UnicodeChar != CHAR_CARRIAGE_RETURN); - - // - // The initial value of the orderedlist is invalid, force to be valid value - // Exit current DisplayForm with new value. - // - gUserInput->SelectedStatement = Question; - - ValueArray = AllocateCopyPool (Question->CurrentValue.BufferLen, Question->CurrentValue.Buffer); - ASSERT (ValueArray != NULL); - gUserInput->InputValue.Buffer = ValueArray; - gUserInput->InputValue.BufferLen = Question->CurrentValue.BufferLen; - gUserInput->InputValue.Type = Question->CurrentValue.Type; - } - - SetArrayData (ValueArray, ValueType, Index++, OneOfOption->OptionOpCode->Value.u64); - } - - if (ValueInvalid) { - FreePool (*OptionString); - *OptionString = NULL; - return EFI_NOT_FOUND; - } - } - break; - - case EFI_IFR_ONE_OF_OP: - // - // Check whether there are Options of this OneOf - // - if (IsListEmpty (&Question->OptionListHead)) { - break; - } - if (Selected) { - // - // Go ask for input - // - Status = GetSelectionInputPopUp (MenuOption); - } else { - *OptionString = AllocateZeroPool (BufferSize); - ASSERT (*OptionString); - - OneOfOption = ValueToOption (Question, QuestionValue); - if (OneOfOption == NULL) { - if (SkipErrorValue) { - // - // Not report error, just get the correct option string info. - // - Link = GetFirstNode (&Question->OptionListHead); - OneOfOption = DISPLAY_QUESTION_OPTION_FROM_LINK (Link); - } else { - // - // Show error message - // - do { - CreateDialog (&Key, gEmptyString, gOptionMismatch, gPressEnter, gEmptyString, NULL); - } while (Key.UnicodeChar != CHAR_CARRIAGE_RETURN); - - // - // Force the Question value to be valid - // Exit current DisplayForm with new value. - // - Link = GetFirstNode (&Question->OptionListHead); - Option = DISPLAY_QUESTION_OPTION_FROM_LINK (Link); - - CopyMem (&gUserInput->InputValue.Value, &Option->OptionOpCode->Value, sizeof (EFI_IFR_TYPE_VALUE)); - gUserInput->InputValue.Type = Option->OptionOpCode->Type; - gUserInput->SelectedStatement = Question; - - FreePool (*OptionString); - *OptionString = NULL; - return EFI_NOT_FOUND; - } - } - - Character[0] = LEFT_ONEOF_DELIMITER; - NewStrCat (OptionString[0], Character); - StringPtr = GetToken (OneOfOption->OptionOpCode->Option, gFormData->HiiHandle); - ASSERT (StringPtr != NULL); - NewStrCat (OptionString[0], StringPtr); - Character[0] = RIGHT_ONEOF_DELIMITER; - NewStrCat (OptionString[0], Character); - - FreePool (StringPtr); - } - break; - - case EFI_IFR_CHECKBOX_OP: - if (Selected) { - // - // Since this is a BOOLEAN operation, flip it upon selection - // - gUserInput->InputValue.Type = QuestionValue->Type; - gUserInput->InputValue.Value.b = (BOOLEAN) (QuestionValue->Value.b ? FALSE : TRUE); - - // - // Perform inconsistent check - // - return ValidateQuestion (Question); - } else { - *OptionString = AllocateZeroPool (BufferSize); - ASSERT (*OptionString); - - *OptionString[0] = LEFT_CHECKBOX_DELIMITER; - - if (QuestionValue->Value.b) { - *(OptionString[0] + 1) = CHECK_ON; - } else { - *(OptionString[0] + 1) = CHECK_OFF; - } - *(OptionString[0] + 2) = RIGHT_CHECKBOX_DELIMITER; - } - break; - - case EFI_IFR_NUMERIC_OP: - if (Selected) { - // - // Go ask for input - // - Status = GetNumericInput (MenuOption); - } else { - *OptionString = AllocateZeroPool (BufferSize); - ASSERT (*OptionString); - - *OptionString[0] = LEFT_NUMERIC_DELIMITER; - - // - // Formatted print - // - PrintFormattedNumber (Question, FormattedNumber, 21 * sizeof (CHAR16)); - Number = (UINT16) GetStringWidth (FormattedNumber); - CopyMem (OptionString[0] + 1, FormattedNumber, Number); - - *(OptionString[0] + Number / 2) = RIGHT_NUMERIC_DELIMITER; - } - break; - - case EFI_IFR_DATE_OP: - if (Selected) { - // - // This is similar to numerics - // - Status = GetNumericInput (MenuOption); - } else { - *OptionString = AllocateZeroPool (BufferSize); - ASSERT (*OptionString); - - switch (MenuOption->Sequence) { - case 0: - *OptionString[0] = LEFT_NUMERIC_DELIMITER; - UnicodeSPrint (OptionString[0] + 1, 21 * sizeof (CHAR16), L"%02d", QuestionValue->Value.date.Month); - *(OptionString[0] + 3) = DATE_SEPARATOR; - break; - - case 1: - SetUnicodeMem (OptionString[0], 4, L' '); - UnicodeSPrint (OptionString[0] + 4, 21 * sizeof (CHAR16), L"%02d", QuestionValue->Value.date.Day); - *(OptionString[0] + 6) = DATE_SEPARATOR; - break; - - case 2: - SetUnicodeMem (OptionString[0], 7, L' '); - UnicodeSPrint (OptionString[0] + 7, 21 * sizeof (CHAR16), L"%04d", QuestionValue->Value.date.Year); - *(OptionString[0] + 11) = RIGHT_NUMERIC_DELIMITER; - break; - } - } - break; - - case EFI_IFR_TIME_OP: - if (Selected) { - // - // This is similar to numerics - // - Status = GetNumericInput (MenuOption); - } else { - *OptionString = AllocateZeroPool (BufferSize); - ASSERT (*OptionString); - - switch (MenuOption->Sequence) { - case 0: - *OptionString[0] = LEFT_NUMERIC_DELIMITER; - UnicodeSPrint (OptionString[0] + 1, 21 * sizeof (CHAR16), L"%02d", QuestionValue->Value.time.Hour); - *(OptionString[0] + 3) = TIME_SEPARATOR; - break; - - case 1: - SetUnicodeMem (OptionString[0], 4, L' '); - UnicodeSPrint (OptionString[0] + 4, 21 * sizeof (CHAR16), L"%02d", QuestionValue->Value.time.Minute); - *(OptionString[0] + 6) = TIME_SEPARATOR; - break; - - case 2: - SetUnicodeMem (OptionString[0], 7, L' '); - UnicodeSPrint (OptionString[0] + 7, 21 * sizeof (CHAR16), L"%02d", QuestionValue->Value.time.Second); - *(OptionString[0] + 9) = RIGHT_NUMERIC_DELIMITER; - break; - } - } - break; - - case EFI_IFR_STRING_OP: - if (Selected) { - StringPtr = AllocateZeroPool (Question->CurrentValue.BufferLen + sizeof (CHAR16)); - ASSERT (StringPtr); - CopyMem(StringPtr, Question->CurrentValue.Buffer, Question->CurrentValue.BufferLen); - - Status = ReadString (MenuOption, gPromptForData, StringPtr); - if (EFI_ERROR (Status)) { - FreePool (StringPtr); - return Status; - } - - gUserInput->InputValue.Buffer = AllocateCopyPool (Question->CurrentValue.BufferLen, StringPtr); - gUserInput->InputValue.BufferLen = Question->CurrentValue.BufferLen; - gUserInput->InputValue.Type = Question->CurrentValue.Type; - gUserInput->InputValue.Value.string = HiiSetString(gFormData->HiiHandle, gUserInput->InputValue.Value.string, StringPtr, NULL); - FreePool (StringPtr); - return ValidateQuestion (Question); - } else { - *OptionString = AllocateZeroPool (BufferSize); - ASSERT (*OptionString); - - if (((CHAR16 *) Question->CurrentValue.Buffer)[0] == 0x0000) { - *(OptionString[0]) = '_'; - } else { - if (Question->CurrentValue.BufferLen < BufferSize) { - BufferSize = Question->CurrentValue.BufferLen; - } - CopyMem (OptionString[0], (CHAR16 *) Question->CurrentValue.Buffer, BufferSize); - } - } - break; - - case EFI_IFR_PASSWORD_OP: - if (Selected) { - Status = PasswordProcess (MenuOption); - } - break; - - default: - break; - } - - return Status; -} - - -/** - Process the help string: Split StringPtr to several lines of strings stored in - FormattedString and the glyph width of each line cannot exceed gHelpBlockWidth. - - @param StringPtr The entire help string. - @param FormattedString The oupput formatted string. - @param EachLineWidth The max string length of each line in the formatted string. - @param RowCount TRUE: if Question is selected. - -**/ -UINTN -ProcessHelpString ( - IN CHAR16 *StringPtr, - OUT CHAR16 **FormattedString, - OUT UINT16 *EachLineWidth, - IN UINTN RowCount - ) -{ - UINTN Index; - CHAR16 *OutputString; - UINTN TotalRowNum; - UINTN CheckedNum; - UINT16 GlyphWidth; - UINT16 LineWidth; - UINT16 MaxStringLen; - UINT16 StringLen; - - TotalRowNum = 0; - CheckedNum = 0; - GlyphWidth = 1; - Index = 0; - MaxStringLen = 0; - StringLen = 0; - - // - // Set default help string width. - // - LineWidth = (UINT16) (gHelpBlockWidth - 1); - - // - // Get row number of the String. - // - while ((StringLen = GetLineByWidth (StringPtr, LineWidth, &GlyphWidth, &Index, &OutputString)) != 0) { - if (StringLen > MaxStringLen) { - MaxStringLen = StringLen; - } - - TotalRowNum ++; - FreePool (OutputString); - } - *EachLineWidth = MaxStringLen; - - *FormattedString = AllocateZeroPool (TotalRowNum * MaxStringLen * sizeof (CHAR16)); - ASSERT (*FormattedString != NULL); - - // - // Generate formatted help string array. - // - GlyphWidth = 1; - Index = 0; - while((StringLen = GetLineByWidth (StringPtr, LineWidth, &GlyphWidth, &Index, &OutputString)) != 0) { - CopyMem (*FormattedString + CheckedNum * MaxStringLen, OutputString, StringLen * sizeof (CHAR16)); - CheckedNum ++; - FreePool (OutputString); - } - - return TotalRowNum; -} diff --git a/MdeModulePkg/Universal/SetupBrowserDxe/Colors.h b/MdeModulePkg/Universal/SetupBrowserDxe/Colors.h new file mode 100644 index 0000000000..2db8b99614 --- /dev/null +++ b/MdeModulePkg/Universal/SetupBrowserDxe/Colors.h @@ -0,0 +1,44 @@ +/** @file +MACRO definitions for color used in Setup Browser. + +Copyright (c) 2004 - 2011, Intel Corporation. All rights reserved.
+This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ +// +// Unicode collation protocol in + +#ifndef _COLORS_H_ +#define _COLORS_H_ + +// +// Screen Color Settings +// +#define PICKLIST_HIGHLIGHT_TEXT EFI_WHITE +#define PICKLIST_HIGHLIGHT_BACKGROUND EFI_BACKGROUND_CYAN +#define TITLE_TEXT EFI_WHITE +#define TITLE_BACKGROUND EFI_BACKGROUND_BLUE +#define KEYHELP_TEXT EFI_LIGHTGRAY +#define KEYHELP_BACKGROUND EFI_BACKGROUND_BLACK +#define SUBTITLE_BACKGROUND EFI_BACKGROUND_LIGHTGRAY +#define BANNER_TEXT EFI_BLUE +#define BANNER_BACKGROUND EFI_BACKGROUND_LIGHTGRAY +#define FIELD_TEXT_GRAYED EFI_DARKGRAY +#define FIELD_BACKGROUND EFI_BACKGROUND_LIGHTGRAY +#define POPUP_TEXT EFI_LIGHTGRAY +#define POPUP_BACKGROUND EFI_BACKGROUND_BLUE +#define POPUP_INVERSE_TEXT EFI_LIGHTGRAY +#define POPUP_INVERSE_BACKGROUND EFI_BACKGROUND_BLACK +#define HELP_TEXT EFI_BLUE +#define ERROR_TEXT EFI_RED | EFI_BRIGHT +#define INFO_TEXT EFI_YELLOW | EFI_BRIGHT +#define ARROW_TEXT EFI_RED | EFI_BRIGHT +#define ARROW_BACKGROUND EFI_BACKGROUND_LIGHTGRAY + +#endif diff --git a/MdeModulePkg/Universal/SetupBrowserDxe/Expression.c b/MdeModulePkg/Universal/SetupBrowserDxe/Expression.c index 44dae1ba03..cd29e29438 100644 --- a/MdeModulePkg/Universal/SetupBrowserDxe/Expression.c +++ b/MdeModulePkg/Universal/SetupBrowserDxe/Expression.c @@ -787,7 +787,7 @@ FORM_BROWSER_FORM * IdToForm ( IN FORM_BROWSER_FORMSET *FormSet, IN UINT16 FormId - ) +) { LIST_ENTRY *Link; FORM_BROWSER_FORM *Form; @@ -2105,7 +2105,7 @@ GetQuestionValueFromForm ( // FormSet = AllocateZeroPool (sizeof (FORM_BROWSER_FORMSET)); ASSERT (FormSet != NULL); - Status = InitializeFormSet(HiiHandle, FormSetGuid, FormSet); + Status = InitializeFormSet(HiiHandle, FormSetGuid, FormSet, FALSE); if (EFI_ERROR (Status)) { GetTheVal = FALSE; goto Done; @@ -2800,7 +2800,7 @@ EvaluateExpression ( for (Index = 0; Index < OpCode->ValueWidth; Index ++, TempBuffer --) { StrPtr += UnicodeValueToString (StrPtr, PREFIX_ZERO | RADIX_HEX, *TempBuffer, 2); } - Status = SetValueByName (OpCode->VarStorage, OpCode->ValueName, NameValue, GetSetValueWithEditBuffer, NULL); + Status = SetValueByName (OpCode->VarStorage, OpCode->ValueName, NameValue, GetSetValueWithEditBuffer); FreePool (NameValue); if (!EFI_ERROR (Status)) { Data1.Value.b = TRUE; diff --git a/MdeModulePkg/Universal/SetupBrowserDxe/Expression.h b/MdeModulePkg/Universal/SetupBrowserDxe/Expression.h deleted file mode 100644 index 5660a997b8..0000000000 --- a/MdeModulePkg/Universal/SetupBrowserDxe/Expression.h +++ /dev/null @@ -1,265 +0,0 @@ -/** @file -Private structure, MACRO and function definitions for User Interface related functionalities. - -Copyright (c) 2004 - 2013, Intel Corporation. All rights reserved.
-This program and the accompanying materials -are licensed and made available under the terms and conditions of the BSD License -which accompanies this distribution. The full text of the license may be found at -http://opensource.org/licenses/bsd-license.php - -THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, -WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. - -**/ - -#ifndef _EXPRESSION_H_ -#define _EXPRESSION_H_ - -/** - Get the expression list count. - - @param Level Which type this expression belong to. Form, - statement or option? - - @retval >=0 The expression count - @retval -1 Input parameter error. - -**/ -INTN -GetConditionalExpressionCount ( - IN EXPRESS_LEVEL Level - ); - -/** - Reset stack pointer to begin of the stack. - -**/ -VOID -ResetCurrentExpressionStack ( - VOID - ); - -/** - Reset stack pointer to begin of the stack. - -**/ -VOID -ResetMapExpressionListStack ( - VOID - ); - -/** - Reset stack pointer to begin of the stack. - -**/ -VOID -ResetScopeStack ( - VOID - ); - -/** - Push an Operand onto the Stack - - @param Operand Operand to push. - - @retval EFI_SUCCESS The value was pushed onto the stack. - @retval EFI_OUT_OF_RESOURCES There is not enough system memory to grow the - stack. - -**/ -EFI_STATUS -PushScope ( - IN UINT8 Operand - ); - -/** - Get the expression Buffer pointer. - - @param Level Which type this expression belong to. Form, - statement or option? - - @retval The start pointer of the expression buffer or NULL. - -**/ -FORM_EXPRESSION ** -GetConditionalExpressionList ( - IN EXPRESS_LEVEL Level - ); - -/** - Pop an Operand from the Stack - - @param Operand Operand to pop. - - @retval EFI_SUCCESS The value was pushed onto the stack. - @retval EFI_OUT_OF_RESOURCES There is not enough system memory to grow the - stack. - -**/ -EFI_STATUS -PopScope ( - OUT UINT8 *Operand - ); - -/** - Push the list of map expression onto the Stack - - @param Pointer Pointer to the list of map expression to be pushed. - - @retval EFI_SUCCESS The value was pushed onto the stack. - @retval EFI_OUT_OF_RESOURCES There is not enough system memory to grow the stack. - -**/ -EFI_STATUS -PushMapExpressionList ( - IN VOID *Pointer - ); - -/** - Push current expression onto the Stack - - @param Pointer Pointer to current expression. - - @retval EFI_SUCCESS The value was pushed onto the stack. - @retval EFI_OUT_OF_RESOURCES There is not enough system memory to grow the stack. - -**/ -EFI_STATUS -PushCurrentExpression ( - IN VOID *Pointer - ); - -/** - Zero extend integer/boolean/date/time to UINT64 for comparing. - - @param Value HII Value to be converted. - -**/ -VOID -ExtendValueToU64 ( - IN EFI_HII_VALUE *Value - ); - -/** - Push the expression options onto the Stack. - - @param Pointer Pointer to the current expression. - @param Level Which type this expression belong to. Form, - statement or option? - - @retval EFI_SUCCESS The value was pushed onto the stack. - @retval EFI_OUT_OF_RESOURCES There is not enough system memory to grow the stack. - -**/ -EFI_STATUS -PushConditionalExpression ( - IN FORM_EXPRESSION *Pointer, - IN EXPRESS_LEVEL Level - ); - -/** - Pop the expression options from the Stack - - @param Level Which type this expression belong to. Form, - statement or option? - - @retval EFI_SUCCESS The value was pushed onto the stack. - @retval EFI_OUT_OF_RESOURCES There is not enough system memory to grow the stack. - -**/ -EFI_STATUS -PopConditionalExpression ( - IN EXPRESS_LEVEL Level - ); - -/** - Pop the list of map expression from the Stack - - @param Pointer Pointer to the list of map expression to be pop. - - @retval EFI_SUCCESS The value was pushed onto the stack. - @retval EFI_OUT_OF_RESOURCES There is not enough system memory to grow the stack. - -**/ -EFI_STATUS -PopMapExpressionList ( - OUT VOID **Pointer - ); - -/** - Pop current expression from the Stack - - @param Pointer Pointer to current expression to be pop. - - @retval EFI_SUCCESS The value was pushed onto the stack. - @retval EFI_OUT_OF_RESOURCES There is not enough system memory to grow the stack. - -**/ -EFI_STATUS -PopCurrentExpression ( - OUT VOID **Pointer - ); - -/** - Evaluate the result of a HII expression. - - If Expression is NULL, then ASSERT. - - @param FormSet FormSet associated with this expression. - @param Form Form associated with this expression. - @param Expression Expression to be evaluated. - - @retval EFI_SUCCESS The expression evaluated successfuly - @retval EFI_NOT_FOUND The Question which referenced by a QuestionId - could not be found. - @retval EFI_OUT_OF_RESOURCES There is not enough system memory to grow the - stack. - @retval EFI_ACCESS_DENIED The pop operation underflowed the stack - @retval EFI_INVALID_PARAMETER Syntax error with the Expression - -**/ -EFI_STATUS -EvaluateExpression ( - IN FORM_BROWSER_FORMSET *FormSet, - IN FORM_BROWSER_FORM *Form, - IN OUT FORM_EXPRESSION *Expression - ); -/** - Return the result of the expression list. Check the expression list and - return the highest priority express result. - Priority: DisableIf > SuppressIf > GrayOutIf > FALSE - - @param ExpList The input expression list. - @param Evaluate Whether need to evaluate the expression first. - @param FormSet FormSet associated with this expression. - @param Form Form associated with this expression. - - @retval EXPRESS_RESULT Return the higher priority express result. - DisableIf > SuppressIf > GrayOutIf > FALSE - -**/ -EXPRESS_RESULT -EvaluateExpressionList ( - IN FORM_EXPRESSION_LIST *ExpList, - IN BOOLEAN Evaluate, - IN FORM_BROWSER_FORMSET *FormSet, OPTIONAL - IN FORM_BROWSER_FORM *Form OPTIONAL - ); - -/** - Get Form given its FormId. - - @param FormSet The formset which contains this form. - @param FormId Id of this form. - - @retval Pointer The form. - @retval NULL Specified Form is not found in the formset. - -**/ -FORM_BROWSER_FORM * -IdToForm ( - IN FORM_BROWSER_FORMSET *FormSet, - IN UINT16 FormId - ); - -#endif // _EXPRESSION_H diff --git a/MdeModulePkg/Universal/SetupBrowserDxe/IfrParse.c b/MdeModulePkg/Universal/SetupBrowserDxe/IfrParse.c index 1c3ab2bedc..2464aebd09 100644 --- a/MdeModulePkg/Universal/SetupBrowserDxe/IfrParse.c +++ b/MdeModulePkg/Universal/SetupBrowserDxe/IfrParse.c @@ -16,7 +16,7 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. UINT16 mStatementIndex; UINT16 mExpressionOpCodeIndex; -EFI_QUESTION_ID mUsedQuestionId; + BOOLEAN mInScopeSubtitle; extern LIST_ENTRY gBrowserStorageList; /** @@ -42,9 +42,9 @@ CreateStatement ( if (Form == NULL) { // - // Only guid op may out side the form level. + // We are currently not in a Form Scope, so just skip this Statement // - ASSERT (((EFI_IFR_OP_HEADER *) OpCodeData)->OpCode == EFI_IFR_GUID_OP); + return NULL; } Statement = &FormSet->StatementBuffer[mStatementIndex]; @@ -58,7 +58,6 @@ CreateStatement ( Statement->Signature = FORM_BROWSER_STATEMENT_SIGNATURE; Statement->Operand = ((EFI_IFR_OP_HEADER *) OpCodeData)->OpCode; - Statement->OpCode = (EFI_IFR_OP_HEADER *) OpCodeData; StatementHdr = (EFI_IFR_STATEMENT_HEADER *) (OpCodeData + sizeof (EFI_IFR_OP_HEADER)); CopyMem (&Statement->Prompt, &StatementHdr->Prompt, sizeof (EFI_STRING_ID)); @@ -83,11 +82,8 @@ CreateStatement ( // // Insert this Statement into current Form // - if (Form == NULL) { - InsertTailList (&FormSet->StatementListOSF, &Statement->Link); - } else { - InsertTailList (&Form->StatementListHead, &Statement->Link); - } + InsertTailList (&Form->StatementListHead, &Statement->Link); + return Statement; } @@ -1137,7 +1133,6 @@ ParseOpCodes ( CountOpCodes (FormSet, &NumberOfStatement, &NumberOfExpression); mStatementIndex = 0; - mUsedQuestionId = 1; FormSet->StatementBuffer = AllocateZeroPool (NumberOfStatement * sizeof (FORM_BROWSER_STATEMENT)); if (FormSet->StatementBuffer == NULL) { return EFI_OUT_OF_RESOURCES; @@ -1149,7 +1144,6 @@ ParseOpCodes ( return EFI_OUT_OF_RESOURCES; } - InitializeListHead (&FormSet->StatementListOSF); InitializeListHead (&FormSet->StorageListHead); InitializeListHead (&FormSet->DefaultStoreListHead); InitializeListHead (&FormSet->FormListHead); @@ -1508,6 +1502,7 @@ ParseOpCodes ( InitializeListHead (&CurrentForm->ConfigRequestHead); CurrentForm->FormType = STANDARD_MAP_FORM_TYPE; + CurrentForm->NvUpdateRequired = FALSE; CopyMem (&CurrentForm->FormId, &((EFI_IFR_FORM *) OpCodeData)->FormId, sizeof (UINT16)); CopyMem (&CurrentForm->FormTitle, &((EFI_IFR_FORM *) OpCodeData)->FormTitle, sizeof (EFI_STRING_ID)); @@ -1544,6 +1539,7 @@ ParseOpCodes ( CurrentForm = AllocateZeroPool (sizeof (FORM_BROWSER_FORM)); ASSERT (CurrentForm != NULL); CurrentForm->Signature = FORM_BROWSER_FORM_SIGNATURE; + CurrentForm->NvUpdateRequired = FALSE; InitializeListHead (&CurrentForm->ExpressionListHead); InitializeListHead (&CurrentForm->StatementListHead); InitializeListHead (&CurrentForm->ConfigRequestHead); @@ -1657,7 +1653,7 @@ ParseOpCodes ( ASSERT (CurrentStatement != NULL); CurrentStatement->Flags = ((EFI_IFR_SUBTITLE *) OpCodeData)->Flags; - CurrentStatement->FakeQuestionId = mUsedQuestionId++; + if (Scope != 0) { mInScopeSubtitle = TRUE; } @@ -1666,14 +1662,13 @@ ParseOpCodes ( case EFI_IFR_TEXT_OP: CurrentStatement = CreateStatement (OpCodeData, FormSet, CurrentForm); ASSERT (CurrentStatement != NULL); - CurrentStatement->FakeQuestionId = mUsedQuestionId++; + CopyMem (&CurrentStatement->TextTwo, &((EFI_IFR_TEXT *) OpCodeData)->TextTwo, sizeof (EFI_STRING_ID)); break; case EFI_IFR_RESET_BUTTON_OP: CurrentStatement = CreateStatement (OpCodeData, FormSet, CurrentForm); ASSERT (CurrentStatement != NULL); - CurrentStatement->FakeQuestionId = mUsedQuestionId++; CopyMem (&CurrentStatement->DefaultId, &((EFI_IFR_RESET_BUTTON *) OpCodeData)->DefaultId, sizeof (EFI_DEFAULT_ID)); break; @@ -1918,7 +1913,6 @@ ParseOpCodes ( CurrentOption = AllocateZeroPool (sizeof (QUESTION_OPTION)); ASSERT (CurrentOption != NULL); CurrentOption->Signature = QUESTION_OPTION_SIGNATURE; - CurrentOption->OpCode = (EFI_IFR_ONE_OF_OPTION *) OpCodeData; CurrentOption->Flags = ((EFI_IFR_ONE_OF_OPTION *) OpCodeData)->Flags; CurrentOption->Value.Type = ((EFI_IFR_ONE_OF_OPTION *) OpCodeData)->Type; @@ -2276,8 +2270,45 @@ ParseOpCodes ( // // Vendor specific // - case EFI_IFR_GUID_OP: - CurrentStatement = CreateStatement (OpCodeData, FormSet, CurrentForm); + case EFI_IFR_GUID_OP: + if (CompareGuid (&gEfiIfrTianoGuid, (EFI_GUID *)(OpCodeData + sizeof (EFI_IFR_OP_HEADER)))) { + // + // Tiano specific GUIDed opcodes + // + switch (((EFI_IFR_GUID_LABEL *) OpCodeData)->ExtendOpCode) { + case EFI_IFR_EXTEND_OP_LABEL: + // + // just ignore label + // + break; + + case EFI_IFR_EXTEND_OP_BANNER: + // + // By SubClass to get Banner Data from Front Page + // + if (FormSet->SubClass == EFI_FRONT_PAGE_SUBCLASS) { + CopyMem ( + &gBannerData->Banner[((EFI_IFR_GUID_BANNER *) OpCodeData)->LineNumber][ + ((EFI_IFR_GUID_BANNER *) OpCodeData)->Alignment], + &((EFI_IFR_GUID_BANNER *) OpCodeData)->Title, + sizeof (EFI_STRING_ID) + ); + } + break; + + case EFI_IFR_EXTEND_OP_CLASS: + CopyMem (&FormSet->Class, &((EFI_IFR_GUID_CLASS *) OpCodeData)->Class, sizeof (UINT16)); + break; + + case EFI_IFR_EXTEND_OP_SUBCLASS: + CopyMem (&FormSet->SubClass, &((EFI_IFR_GUID_SUBCLASS *) OpCodeData)->SubClass, sizeof (UINT16)); + break; + + default: + break; + } + } + break; // diff --git a/MdeModulePkg/Universal/SetupBrowserDxe/InputHandler.c b/MdeModulePkg/Universal/SetupBrowserDxe/InputHandler.c new file mode 100644 index 0000000000..844590770a --- /dev/null +++ b/MdeModulePkg/Universal/SetupBrowserDxe/InputHandler.c @@ -0,0 +1,1418 @@ +/** @file +Implementation for handling user input from the User Interfaces. + +Copyright (c) 2004 - 2012, Intel Corporation. All rights reserved.
+This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include "Setup.h" + + +/** + Get string or password input from user. + + @param MenuOption Pointer to the current input menu. + @param Prompt The prompt string shown on popup window. + @param StringPtr Old user input and destination for use input string. + + @retval EFI_SUCCESS If string input is read successfully + @retval EFI_DEVICE_ERROR If operation fails + +**/ +EFI_STATUS +ReadString ( + IN UI_MENU_OPTION *MenuOption, + IN CHAR16 *Prompt, + IN OUT CHAR16 *StringPtr + ) +{ + EFI_STATUS Status; + EFI_INPUT_KEY Key; + CHAR16 NullCharacter; + UINTN ScreenSize; + CHAR16 Space[2]; + CHAR16 KeyPad[2]; + CHAR16 *TempString; + CHAR16 *BufferedString; + UINTN Index; + UINTN Index2; + UINTN Count; + UINTN Start; + UINTN Top; + UINTN DimensionsWidth; + UINTN DimensionsHeight; + UINTN CurrentCursor; + BOOLEAN CursorVisible; + UINTN Minimum; + UINTN Maximum; + FORM_BROWSER_STATEMENT *Question; + BOOLEAN IsPassword; + + DimensionsWidth = gScreenDimensions.RightColumn - gScreenDimensions.LeftColumn; + DimensionsHeight = gScreenDimensions.BottomRow - gScreenDimensions.TopRow; + + NullCharacter = CHAR_NULL; + ScreenSize = GetStringWidth (Prompt) / sizeof (CHAR16); + Space[0] = L' '; + Space[1] = CHAR_NULL; + + Question = MenuOption->ThisTag; + Minimum = (UINTN) Question->Minimum; + Maximum = (UINTN) Question->Maximum; + + if (Question->Operand == EFI_IFR_PASSWORD_OP) { + IsPassword = TRUE; + } else { + IsPassword = FALSE; + } + + TempString = AllocateZeroPool ((Maximum + 1)* sizeof (CHAR16)); + ASSERT (TempString); + + if (ScreenSize < (Maximum + 1)) { + ScreenSize = Maximum + 1; + } + + if ((ScreenSize + 2) > DimensionsWidth) { + ScreenSize = DimensionsWidth - 2; + } + + BufferedString = AllocateZeroPool (ScreenSize * 2); + ASSERT (BufferedString); + + Start = (DimensionsWidth - ScreenSize - 2) / 2 + gScreenDimensions.LeftColumn + 1; + Top = ((DimensionsHeight - 6) / 2) + gScreenDimensions.TopRow - 1; + + // + // Display prompt for string + // + CreateMultiStringPopUp (ScreenSize, 4, &NullCharacter, Prompt, Space, &NullCharacter); + + gST->ConOut->SetAttribute (gST->ConOut, EFI_TEXT_ATTR (EFI_BLACK, EFI_LIGHTGRAY)); + + CursorVisible = gST->ConOut->Mode->CursorVisible; + gST->ConOut->EnableCursor (gST->ConOut, TRUE); + + CurrentCursor = GetStringWidth (StringPtr) / 2 - 1; + if (CurrentCursor != 0) { + // + // Show the string which has beed saved before. + // + SetUnicodeMem (BufferedString, ScreenSize - 1, L' '); + PrintStringAt (Start + 1, Top + 3, BufferedString); + + if ((GetStringWidth (StringPtr) / 2) > (DimensionsWidth - 2)) { + Index = (GetStringWidth (StringPtr) / 2) - DimensionsWidth + 2; + } else { + Index = 0; + } + + if (IsPassword) { + gST->ConOut->SetCursorPosition (gST->ConOut, Start + 1, Top + 3); + } + + for (Count = 0; Index + 1 < GetStringWidth (StringPtr) / 2; Index++, Count++) { + BufferedString[Count] = StringPtr[Index]; + + if (IsPassword) { + PrintChar (L'*'); + } + } + + if (!IsPassword) { + PrintStringAt (Start + 1, Top + 3, BufferedString); + } + + gST->ConOut->SetAttribute (gST->ConOut, EFI_TEXT_ATTR (EFI_LIGHTGRAY, EFI_BLACK)); + gST->ConOut->SetCursorPosition (gST->ConOut, Start + GetStringWidth (StringPtr) / 2, Top + 3); + } + + do { + Status = WaitForKeyStroke (&Key); + ASSERT_EFI_ERROR (Status); + + gST->ConOut->SetAttribute (gST->ConOut, EFI_TEXT_ATTR (EFI_BLACK, EFI_LIGHTGRAY)); + switch (Key.UnicodeChar) { + case CHAR_NULL: + switch (Key.ScanCode) { + case SCAN_LEFT: + if (CurrentCursor > 0) { + CurrentCursor--; + } + break; + + case SCAN_RIGHT: + if (CurrentCursor < (GetStringWidth (StringPtr) / 2 - 1)) { + CurrentCursor++; + } + break; + + case SCAN_ESC: + FreePool (TempString); + FreePool (BufferedString); + gST->ConOut->SetAttribute (gST->ConOut, EFI_TEXT_ATTR (EFI_LIGHTGRAY, EFI_BLACK)); + gST->ConOut->EnableCursor (gST->ConOut, CursorVisible); + return EFI_DEVICE_ERROR; + + default: + break; + } + + break; + + case CHAR_CARRIAGE_RETURN: + if (GetStringWidth (StringPtr) >= ((Minimum + 1) * sizeof (CHAR16))) { + + FreePool (TempString); + FreePool (BufferedString); + gST->ConOut->SetAttribute (gST->ConOut, EFI_TEXT_ATTR (EFI_LIGHTGRAY, EFI_BLACK)); + gST->ConOut->EnableCursor (gST->ConOut, CursorVisible); + return EFI_SUCCESS; + } else { + // + // Simply create a popup to tell the user that they had typed in too few characters. + // To save code space, we can then treat this as an error and return back to the menu. + // + do { + CreateDialog (4, TRUE, 0, NULL, &Key, &NullCharacter, gMiniString, gPressEnter, &NullCharacter); + } while (Key.UnicodeChar != CHAR_CARRIAGE_RETURN); + + FreePool (TempString); + FreePool (BufferedString); + gST->ConOut->SetAttribute (gST->ConOut, EFI_TEXT_ATTR (EFI_LIGHTGRAY, EFI_BLACK)); + gST->ConOut->EnableCursor (gST->ConOut, CursorVisible); + return EFI_DEVICE_ERROR; + } + + break; + + case CHAR_BACKSPACE: + if (StringPtr[0] != CHAR_NULL && CurrentCursor != 0) { + for (Index = 0; Index < CurrentCursor - 1; Index++) { + TempString[Index] = StringPtr[Index]; + } + Count = GetStringWidth (StringPtr) / 2 - 1; + if (Count >= CurrentCursor) { + for (Index = CurrentCursor - 1, Index2 = CurrentCursor; Index2 < Count; Index++, Index2++) { + TempString[Index] = StringPtr[Index2]; + } + TempString[Index] = CHAR_NULL; + } + // + // Effectively truncate string by 1 character + // + StrCpy (StringPtr, TempString); + CurrentCursor --; + } + + default: + // + // If it is the beginning of the string, don't worry about checking maximum limits + // + if ((StringPtr[0] == CHAR_NULL) && (Key.UnicodeChar != CHAR_BACKSPACE)) { + StrnCpy (StringPtr, &Key.UnicodeChar, 1); + CurrentCursor++; + } else if ((GetStringWidth (StringPtr) < ((Maximum + 1) * sizeof (CHAR16))) && (Key.UnicodeChar != CHAR_BACKSPACE)) { + KeyPad[0] = Key.UnicodeChar; + KeyPad[1] = CHAR_NULL; + Count = GetStringWidth (StringPtr) / 2 - 1; + if (CurrentCursor < Count) { + for (Index = 0; Index < CurrentCursor; Index++) { + TempString[Index] = StringPtr[Index]; + } + TempString[Index] = CHAR_NULL; + StrCat (TempString, KeyPad); + StrCat (TempString, StringPtr + CurrentCursor); + StrCpy (StringPtr, TempString); + } else { + StrCat (StringPtr, KeyPad); + } + CurrentCursor++; + } + + // + // If the width of the input string is now larger than the screen, we nee to + // adjust the index to start printing portions of the string + // + SetUnicodeMem (BufferedString, ScreenSize - 1, L' '); + PrintStringAt (Start + 1, Top + 3, BufferedString); + + if ((GetStringWidth (StringPtr) / 2) > (DimensionsWidth - 2)) { + Index = (GetStringWidth (StringPtr) / 2) - DimensionsWidth + 2; + } else { + Index = 0; + } + + if (IsPassword) { + gST->ConOut->SetCursorPosition (gST->ConOut, Start + 1, Top + 3); + } + + for (Count = 0; Index + 1 < GetStringWidth (StringPtr) / 2; Index++, Count++) { + BufferedString[Count] = StringPtr[Index]; + + if (IsPassword) { + PrintChar (L'*'); + } + } + + if (!IsPassword) { + PrintStringAt (Start + 1, Top + 3, BufferedString); + } + break; + } + + gST->ConOut->SetAttribute (gST->ConOut, EFI_TEXT_ATTR (EFI_LIGHTGRAY, EFI_BLACK)); + gST->ConOut->SetCursorPosition (gST->ConOut, Start + CurrentCursor + 1, Top + 3); + } while (TRUE); + +} + +/** + Adjust the value to the correct one. Rules follow the sample: + like: Year change: 2012.02.29 -> 2013.02.29 -> 2013.02.01 + Month change: 2013.03.29 -> 2013.02.29 -> 2013.02.28 + + @param Question Pointer to current question. + @param Sequence The sequence of the field in the question. +**/ +VOID +AdjustQuestionValue ( + IN FORM_BROWSER_STATEMENT *Question, + IN UINT8 Sequence + ) +{ + UINT8 Month; + UINT16 Year; + UINT8 Maximum; + UINT8 Minimum; + + if (Question->Operand != EFI_IFR_DATE_OP) { + return; + } + + Month = Question->HiiValue.Value.date.Month; + Year = Question->HiiValue.Value.date.Year; + Minimum = 1; + + switch (Month) { + case 2: + if ((Year % 4) == 0 && ((Year % 100) != 0 || (Year % 400) == 0)) { + Maximum = 29; + } else { + Maximum = 28; + } + break; + case 4: + case 6: + case 9: + case 11: + Maximum = 30; + break; + default: + Maximum = 31; + break; + } + + // + // Change the month area. + // + if (Sequence == 0) { + if (Question->HiiValue.Value.date.Day > Maximum) { + Question->HiiValue.Value.date.Day = Maximum; + } + } + + // + // Change the Year area. + // + if (Sequence == 2) { + if (Question->HiiValue.Value.date.Day > Maximum) { + Question->HiiValue.Value.date.Day = Minimum; + } + } +} + +/** + This routine reads a numeric value from the user input. + + @param Selection Pointer to current selection. + @param MenuOption Pointer to the current input menu. + + @retval EFI_SUCCESS If numerical input is read successfully + @retval EFI_DEVICE_ERROR If operation fails + +**/ +EFI_STATUS +GetNumericInput ( + IN UI_MENU_SELECTION *Selection, + IN UI_MENU_OPTION *MenuOption + ) +{ + EFI_STATUS Status; + UINTN Column; + UINTN Row; + CHAR16 InputText[MAX_NUMERIC_INPUT_WIDTH]; + CHAR16 FormattedNumber[MAX_NUMERIC_INPUT_WIDTH - 1]; + UINT64 PreviousNumber[MAX_NUMERIC_INPUT_WIDTH - 3]; + UINTN Count; + UINTN Loop; + BOOLEAN ManualInput; + BOOLEAN HexInput; + BOOLEAN DateOrTime; + UINTN InputWidth; + UINT64 EditValue; + UINT64 Step; + UINT64 Minimum; + UINT64 Maximum; + UINTN EraseLen; + UINT8 Digital; + EFI_INPUT_KEY Key; + EFI_HII_VALUE *QuestionValue; + FORM_BROWSER_FORM *Form; + FORM_BROWSER_FORMSET *FormSet; + FORM_BROWSER_STATEMENT *Question; + + Column = MenuOption->OptCol; + Row = MenuOption->Row; + PreviousNumber[0] = 0; + Count = 0; + InputWidth = 0; + Digital = 0; + + FormSet = Selection->FormSet; + Form = Selection->Form; + Question = MenuOption->ThisTag; + QuestionValue = &Question->HiiValue; + Step = Question->Step; + Minimum = Question->Minimum; + Maximum = Question->Maximum; + + // + // Only two case, user can enter to this function: Enter and +/- case. + // In Enter case, gDirection = 0; in +/- case, gDirection = SCAN_LEFT/SCAN_WRIGHT + // + ManualInput = (BOOLEAN)(gDirection == 0 ? TRUE : FALSE); + + if ((Question->Operand == EFI_IFR_DATE_OP) || (Question->Operand == EFI_IFR_TIME_OP)) { + DateOrTime = TRUE; + } else { + DateOrTime = FALSE; + } + + // + // Prepare Value to be edit + // + EraseLen = 0; + EditValue = 0; + if (Question->Operand == EFI_IFR_DATE_OP) { + Step = 1; + Minimum = 1; + + switch (MenuOption->Sequence) { + case 0: + Maximum = 12; + EraseLen = 4; + EditValue = QuestionValue->Value.date.Month; + break; + + case 1: + switch (QuestionValue->Value.date.Month) { + case 2: + if ((QuestionValue->Value.date.Year % 4) == 0 && + ((QuestionValue->Value.date.Year % 100) != 0 || + (QuestionValue->Value.date.Year % 400) == 0)) { + Maximum = 29; + } else { + Maximum = 28; + } + break; + case 4: + case 6: + case 9: + case 11: + Maximum = 30; + break; + default: + Maximum = 31; + break; + } + + EraseLen = 3; + EditValue = QuestionValue->Value.date.Day; + break; + + case 2: + Maximum = 0xffff; + EraseLen = 5; + EditValue = QuestionValue->Value.date.Year; + break; + + default: + break; + } + } else if (Question->Operand == EFI_IFR_TIME_OP) { + Step = 1; + Minimum = 0; + + switch (MenuOption->Sequence) { + case 0: + Maximum = 23; + EraseLen = 4; + EditValue = QuestionValue->Value.time.Hour; + break; + + case 1: + Maximum = 59; + EraseLen = 3; + EditValue = QuestionValue->Value.time.Minute; + break; + + case 2: + Maximum = 59; + EraseLen = 3; + EditValue = QuestionValue->Value.time.Second; + break; + + default: + break; + } + } else { + // + // Numeric + // + EraseLen = gOptionBlockWidth; + EditValue = QuestionValue->Value.u64; + if (Maximum == 0) { + Maximum = (UINT64) -1; + } + } + + if ((Question->Operand == EFI_IFR_NUMERIC_OP) && + ((Question->Flags & EFI_IFR_DISPLAY) == EFI_IFR_DISPLAY_UINT_HEX)) { + HexInput = TRUE; + } else { + HexInput = FALSE; + } + + // + // Enter from "Enter" input, clear the old word showing. + // + if (ManualInput) { + if (Question->Operand == EFI_IFR_NUMERIC_OP) { + if (HexInput) { + InputWidth = Question->StorageWidth * 2; + } else { + switch (Question->StorageWidth) { + case 1: + InputWidth = 3; + break; + + case 2: + InputWidth = 5; + break; + + case 4: + InputWidth = 10; + break; + + case 8: + InputWidth = 20; + break; + + default: + InputWidth = 0; + break; + } + } + + InputText[0] = LEFT_NUMERIC_DELIMITER; + SetUnicodeMem (InputText + 1, InputWidth, L' '); + ASSERT (InputWidth + 2 < MAX_NUMERIC_INPUT_WIDTH); + InputText[InputWidth + 1] = RIGHT_NUMERIC_DELIMITER; + InputText[InputWidth + 2] = L'\0'; + + PrintAt (Column, Row, InputText); + Column++; + } + + if (Question->Operand == EFI_IFR_DATE_OP) { + if (MenuOption->Sequence == 2) { + InputWidth = 4; + } else { + InputWidth = 2; + } + + if (MenuOption->Sequence == 0) { + InputText[0] = LEFT_NUMERIC_DELIMITER; + SetUnicodeMem (InputText + 1, InputWidth, L' '); + } else { + SetUnicodeMem (InputText, InputWidth, L' '); + } + + if (MenuOption->Sequence == 2) { + InputText[InputWidth + 1] = RIGHT_NUMERIC_DELIMITER; + } else { + InputText[InputWidth + 1] = DATE_SEPARATOR; + } + InputText[InputWidth + 2] = L'\0'; + + PrintAt (Column, Row, InputText); + if (MenuOption->Sequence == 0) { + Column++; + } + } + + if (Question->Operand == EFI_IFR_TIME_OP) { + InputWidth = 2; + + if (MenuOption->Sequence == 0) { + InputText[0] = LEFT_NUMERIC_DELIMITER; + SetUnicodeMem (InputText + 1, InputWidth, L' '); + } else { + SetUnicodeMem (InputText, InputWidth, L' '); + } + + if (MenuOption->Sequence == 2) { + InputText[InputWidth + 1] = RIGHT_NUMERIC_DELIMITER; + } else { + InputText[InputWidth + 1] = TIME_SEPARATOR; + } + InputText[InputWidth + 2] = L'\0'; + + PrintAt (Column, Row, InputText); + if (MenuOption->Sequence == 0) { + Column++; + } + } + } + + // + // First time we enter this handler, we need to check to see if + // we were passed an increment or decrement directive + // + do { + Key.UnicodeChar = CHAR_NULL; + if (gDirection != 0) { + Key.ScanCode = gDirection; + gDirection = 0; + goto TheKey2; + } + + Status = WaitForKeyStroke (&Key); + +TheKey2: + switch (Key.UnicodeChar) { + + case '+': + case '-': + if (Key.UnicodeChar == '+') { + Key.ScanCode = SCAN_RIGHT; + } else { + Key.ScanCode = SCAN_LEFT; + } + Key.UnicodeChar = CHAR_NULL; + goto TheKey2; + + case CHAR_NULL: + switch (Key.ScanCode) { + case SCAN_LEFT: + case SCAN_RIGHT: + if (DateOrTime && !ManualInput) { + // + // By setting this value, we will return back to the caller. + // We need to do this since an auto-refresh will destroy the adjustment + // based on what the real-time-clock is showing. So we always commit + // upon changing the value. + // + gDirection = SCAN_DOWN; + } + + if ((Step != 0) && !ManualInput) { + if (Key.ScanCode == SCAN_LEFT) { + if (EditValue >= Minimum + Step) { + EditValue = EditValue - Step; + } else if (EditValue > Minimum){ + EditValue = Minimum; + } else { + EditValue = Maximum; + } + } else if (Key.ScanCode == SCAN_RIGHT) { + if (EditValue + Step <= Maximum) { + EditValue = EditValue + Step; + } else if (EditValue < Maximum) { + EditValue = Maximum; + } else { + EditValue = Minimum; + } + } + + ZeroMem (FormattedNumber, 21 * sizeof (CHAR16)); + if (Question->Operand == EFI_IFR_DATE_OP) { + if (MenuOption->Sequence == 2) { + // + // Year + // + UnicodeSPrint (FormattedNumber, 21 * sizeof (CHAR16), L"%04d", (UINT16) EditValue); + } else { + // + // Month/Day + // + UnicodeSPrint (FormattedNumber, 21 * sizeof (CHAR16), L"%02d", (UINT8) EditValue); + } + + if (MenuOption->Sequence == 0) { + ASSERT (EraseLen >= 2); + FormattedNumber[EraseLen - 2] = DATE_SEPARATOR; + } else if (MenuOption->Sequence == 1) { + ASSERT (EraseLen >= 1); + FormattedNumber[EraseLen - 1] = DATE_SEPARATOR; + } + } else if (Question->Operand == EFI_IFR_TIME_OP) { + UnicodeSPrint (FormattedNumber, 21 * sizeof (CHAR16), L"%02d", (UINT8) EditValue); + + if (MenuOption->Sequence == 0) { + ASSERT (EraseLen >= 2); + FormattedNumber[EraseLen - 2] = TIME_SEPARATOR; + } else if (MenuOption->Sequence == 1) { + ASSERT (EraseLen >= 1); + FormattedNumber[EraseLen - 1] = TIME_SEPARATOR; + } + } else { + QuestionValue->Value.u64 = EditValue; + PrintFormattedNumber (Question, FormattedNumber, 21 * sizeof (CHAR16)); + } + + gST->ConOut->SetAttribute (gST->ConOut, PcdGet8 (PcdBrowserFieldTextColor) | FIELD_BACKGROUND); + for (Loop = 0; Loop < EraseLen; Loop++) { + PrintAt (MenuOption->OptCol + Loop, MenuOption->Row, L" "); + } + gST->ConOut->SetAttribute (gST->ConOut, PcdGet8 (PcdBrowserFieldTextHighlightColor) | PcdGet8 (PcdBrowserFieldBackgroundHighlightColor)); + + if (MenuOption->Sequence == 0) { + PrintCharAt (MenuOption->OptCol, Row, LEFT_NUMERIC_DELIMITER); + Column = MenuOption->OptCol + 1; + } + + PrintStringAt (Column, Row, FormattedNumber); + + if (!DateOrTime || MenuOption->Sequence == 2) { + PrintChar (RIGHT_NUMERIC_DELIMITER); + } + } + + goto EnterCarriageReturn; + break; + + case SCAN_UP: + case SCAN_DOWN: + goto EnterCarriageReturn; + + case SCAN_ESC: + return EFI_DEVICE_ERROR; + + default: + break; + } + + break; + +EnterCarriageReturn: + + case CHAR_CARRIAGE_RETURN: + // + // Validate input value with Minimum value. + // + if (EditValue < Minimum) { + UpdateStatusBar (Selection, INPUT_ERROR, Question->QuestionFlags, TRUE); + break; + } else { + UpdateStatusBar (Selection, INPUT_ERROR, Question->QuestionFlags, FALSE); + } + + // + // Store Edit value back to Question + // + if (Question->Operand == EFI_IFR_DATE_OP) { + switch (MenuOption->Sequence) { + case 0: + QuestionValue->Value.date.Month = (UINT8) EditValue; + break; + + case 1: + QuestionValue->Value.date.Day = (UINT8) EditValue; + break; + + case 2: + QuestionValue->Value.date.Year = (UINT16) EditValue; + break; + + default: + break; + } + } else if (Question->Operand == EFI_IFR_TIME_OP) { + switch (MenuOption->Sequence) { + case 0: + QuestionValue->Value.time.Hour = (UINT8) EditValue; + break; + + case 1: + QuestionValue->Value.time.Minute = (UINT8) EditValue; + break; + + case 2: + QuestionValue->Value.time.Second = (UINT8) EditValue; + break; + + default: + break; + } + } else { + // + // Numeric + // + QuestionValue->Value.u64 = EditValue; + } + + // + // Adjust the value to the correct one. + // Sample like: 2012.02.29 -> 2013.02.29 -> 2013.02.01 + // 2013.03.29 -> 2013.02.29 -> 2013.02.28 + // + if (Question->Operand == EFI_IFR_DATE_OP && + (MenuOption->Sequence == 0 || MenuOption->Sequence == 2)) { + AdjustQuestionValue (Question, (UINT8)MenuOption->Sequence); + } + + // + // Check to see if the Value is something reasonable against consistency limitations. + // If not, let's kick the error specified. + // + Status = ValidateQuestion (FormSet, Form, Question, EFI_HII_EXPRESSION_INCONSISTENT_IF); + if (EFI_ERROR (Status)) { + // + // Input value is not valid, restore Question Value + // + GetQuestionValue (FormSet, Form, Question, GetSetValueWithEditBuffer); + } else { + SetQuestionValue (FormSet, Form, Question, GetSetValueWithEditBuffer); + if (!DateOrTime || (Question->Storage != NULL)) { + // + // NV flag is unnecessary for RTC type of Date/Time + // + UpdateStatusBar (Selection, NV_UPDATE_REQUIRED, Question->QuestionFlags, TRUE); + } + } + + return Status; + break; + + case CHAR_BACKSPACE: + if (ManualInput) { + if (Count == 0) { + break; + } + // + // Remove a character + // + EditValue = PreviousNumber[Count - 1]; + UpdateStatusBar (Selection, INPUT_ERROR, Question->QuestionFlags, FALSE); + Count--; + Column--; + PrintAt (Column, Row, L" "); + } + break; + + default: + if (ManualInput) { + if (HexInput) { + if ((Key.UnicodeChar >= L'0') && (Key.UnicodeChar <= L'9')) { + Digital = (UINT8) (Key.UnicodeChar - L'0'); + } else if ((Key.UnicodeChar >= L'A') && (Key.UnicodeChar <= L'F')) { + Digital = (UINT8) (Key.UnicodeChar - L'A' + 0x0A); + } else if ((Key.UnicodeChar >= L'a') && (Key.UnicodeChar <= L'f')) { + Digital = (UINT8) (Key.UnicodeChar - L'a' + 0x0A); + } else { + UpdateStatusBar (Selection, INPUT_ERROR, Question->QuestionFlags, TRUE); + break; + } + } else { + if (Key.UnicodeChar > L'9' || Key.UnicodeChar < L'0') { + UpdateStatusBar (Selection, INPUT_ERROR, Question->QuestionFlags, TRUE); + break; + } + } + + // + // If Count exceed input width, there is no way more is valid + // + if (Count >= InputWidth) { + break; + } + // + // Someone typed something valid! + // + if (Count != 0) { + if (HexInput) { + EditValue = LShiftU64 (EditValue, 4) + Digital; + } else { + EditValue = MultU64x32 (EditValue, 10) + (Key.UnicodeChar - L'0'); + } + } else { + if (HexInput) { + EditValue = Digital; + } else { + EditValue = Key.UnicodeChar - L'0'; + } + } + + if (EditValue > Maximum) { + UpdateStatusBar (Selection, INPUT_ERROR, Question->QuestionFlags, TRUE); + ASSERT (Count < sizeof (PreviousNumber) / sizeof (PreviousNumber[0])); + EditValue = PreviousNumber[Count]; + break; + } else { + UpdateStatusBar (Selection, INPUT_ERROR, Question->QuestionFlags, FALSE); + } + + Count++; + ASSERT (Count < (sizeof (PreviousNumber) / sizeof (PreviousNumber[0]))); + PreviousNumber[Count] = EditValue; + + PrintCharAt (Column, Row, Key.UnicodeChar); + Column++; + } + break; + } + } while (TRUE); + +} + + +/** + Get selection for OneOf and OrderedList (Left/Right will be ignored). + + @param Selection Pointer to current selection. + @param MenuOption Pointer to the current input menu. + + @retval EFI_SUCCESS If Option input is processed successfully + @retval EFI_DEVICE_ERROR If operation fails + +**/ +EFI_STATUS +GetSelectionInputPopUp ( + IN UI_MENU_SELECTION *Selection, + IN UI_MENU_OPTION *MenuOption + ) +{ + EFI_STATUS Status; + EFI_INPUT_KEY Key; + UINTN Index; + CHAR16 *StringPtr; + CHAR16 *TempStringPtr; + UINTN Index2; + UINTN TopOptionIndex; + UINTN HighlightOptionIndex; + UINTN Start; + UINTN End; + UINTN Top; + UINTN Bottom; + UINTN PopUpMenuLines; + UINTN MenuLinesInView; + UINTN PopUpWidth; + CHAR16 Character; + INT32 SavedAttribute; + BOOLEAN ShowDownArrow; + BOOLEAN ShowUpArrow; + UINTN DimensionsWidth; + LIST_ENTRY *Link; + BOOLEAN OrderedList; + UINT8 *ValueArray; + UINT8 ValueType; + EFI_HII_VALUE HiiValue; + EFI_HII_VALUE *HiiValueArray; + UINTN OptionCount; + QUESTION_OPTION *OneOfOption; + QUESTION_OPTION *CurrentOption; + FORM_BROWSER_STATEMENT *Question; + INTN Result; + + DimensionsWidth = gScreenDimensions.RightColumn - gScreenDimensions.LeftColumn; + + ValueArray = NULL; + ValueType = 0; + CurrentOption = NULL; + ShowDownArrow = FALSE; + ShowUpArrow = FALSE; + + StringPtr = AllocateZeroPool ((gOptionBlockWidth + 1) * 2); + ASSERT (StringPtr); + + Question = MenuOption->ThisTag; + if (Question->Operand == EFI_IFR_ORDERED_LIST_OP) { + ValueArray = Question->BufferValue; + ValueType = Question->ValueType; + OrderedList = TRUE; + } else { + OrderedList = FALSE; + } + + // + // Calculate Option count + // + if (OrderedList) { + for (Index = 0; Index < Question->MaxContainers; Index++) { + if (GetArrayData (ValueArray, ValueType, Index) == 0) { + break; + } + } + + OptionCount = Index; + } else { + OptionCount = 0; + Link = GetFirstNode (&Question->OptionListHead); + while (!IsNull (&Question->OptionListHead, Link)) { + OneOfOption = QUESTION_OPTION_FROM_LINK (Link); + + OptionCount++; + + Link = GetNextNode (&Question->OptionListHead, Link); + } + } + + // + // Move valid Option to list head. + // + PopUpMenuLines = 0; + if (OrderedList) { + // + // Prepare HiiValue array + // + HiiValueArray = AllocateZeroPool (OptionCount * sizeof (EFI_HII_VALUE)); + ASSERT (HiiValueArray != NULL); + for (Index = 0; Index < OptionCount; Index++) { + HiiValueArray[Index].Type = ValueType; + HiiValueArray[Index].Value.u64 = GetArrayData (ValueArray, ValueType, Index); + } + + for (Index = 0; Index < OptionCount; Index++) { + OneOfOption = ValueToOption (Question, &HiiValueArray[OptionCount - Index - 1]); + if (OneOfOption == NULL) { + return EFI_NOT_FOUND; + } + + RemoveEntryList (&OneOfOption->Link); + + // + // Insert to head. + // + InsertHeadList (&Question->OptionListHead, &OneOfOption->Link); + + PopUpMenuLines++; + } + + FreePool (HiiValueArray); + } else { + Link = GetFirstNode (&Question->OptionListHead); + for (Index = 0; Index < OptionCount; Index++) { + OneOfOption = QUESTION_OPTION_FROM_LINK (Link); + Link = GetNextNode (&Question->OptionListHead, Link); + if ((OneOfOption->SuppressExpression != NULL) && + EvaluateExpressionList(OneOfOption->SuppressExpression, FALSE, NULL, NULL) > ExpressFalse) { + continue; + } else { + PopUpMenuLines++; + } + } + } + + // + // Get the number of one of options present and its size + // + PopUpWidth = 0; + HighlightOptionIndex = 0; + Link = GetFirstNode (&Question->OptionListHead); + for (Index = 0; Index < PopUpMenuLines; Index++) { + OneOfOption = QUESTION_OPTION_FROM_LINK (Link); + Link = GetNextNode (&Question->OptionListHead, Link); + + if (!OrderedList && (OneOfOption->SuppressExpression != NULL) && + EvaluateExpressionList(OneOfOption->SuppressExpression, FALSE, NULL, NULL) > ExpressFalse) { + Index--; + continue; + } + + StringPtr = GetToken (OneOfOption->Text, MenuOption->Handle); + if (StrLen (StringPtr) > PopUpWidth) { + PopUpWidth = StrLen (StringPtr); + } + FreePool (StringPtr); + + if (!OrderedList && (CompareHiiValue (&Question->HiiValue, &OneOfOption->Value, &Result, NULL) == EFI_SUCCESS) && (Result == 0)) { + // + // Find current selected Option for OneOf + // + HighlightOptionIndex = Index; + } + } + + // + // Perform popup menu initialization. + // + PopUpWidth = PopUpWidth + POPUP_PAD_SPACE_COUNT; + + SavedAttribute = gST->ConOut->Mode->Attribute; + gST->ConOut->SetAttribute (gST->ConOut, POPUP_TEXT | POPUP_BACKGROUND); + + if ((PopUpWidth + POPUP_FRAME_WIDTH) > DimensionsWidth) { + PopUpWidth = DimensionsWidth - POPUP_FRAME_WIDTH; + } + + Start = (DimensionsWidth - PopUpWidth - POPUP_FRAME_WIDTH) / 2 + gScreenDimensions.LeftColumn; + End = Start + PopUpWidth + POPUP_FRAME_WIDTH; + Top = gScreenDimensions.TopRow + NONE_FRONT_PAGE_HEADER_HEIGHT; + Bottom = gScreenDimensions.BottomRow - STATUS_BAR_HEIGHT - gFooterHeight - 1; + + MenuLinesInView = Bottom - Top - 1; + if (MenuLinesInView >= PopUpMenuLines) { + Top = Top + (MenuLinesInView - PopUpMenuLines) / 2; + Bottom = Top + PopUpMenuLines + 1; + } else { + ShowDownArrow = TRUE; + } + + if (HighlightOptionIndex > (MenuLinesInView - 1)) { + TopOptionIndex = HighlightOptionIndex - MenuLinesInView + 1; + } else { + TopOptionIndex = 0; + } + + do { + // + // Clear that portion of the screen + // + ClearLines (Start, End, Top, Bottom, POPUP_TEXT | POPUP_BACKGROUND); + + // + // Draw "One of" pop-up menu + // + Character = BOXDRAW_DOWN_RIGHT; + PrintCharAt (Start, Top, Character); + for (Index = Start; Index + 2 < End; Index++) { + if ((ShowUpArrow) && ((Index + 1) == (Start + End) / 2)) { + Character = GEOMETRICSHAPE_UP_TRIANGLE; + } else { + Character = BOXDRAW_HORIZONTAL; + } + + PrintChar (Character); + } + + Character = BOXDRAW_DOWN_LEFT; + PrintChar (Character); + Character = BOXDRAW_VERTICAL; + for (Index = Top + 1; Index < Bottom; Index++) { + PrintCharAt (Start, Index, Character); + PrintCharAt (End - 1, Index, Character); + } + + // + // Move to top Option + // + Link = GetFirstNode (&Question->OptionListHead); + for (Index = 0; Index < TopOptionIndex; Index++) { + Link = GetNextNode (&Question->OptionListHead, Link); + + OneOfOption = QUESTION_OPTION_FROM_LINK (Link); + if (!OrderedList && (OneOfOption->SuppressExpression != NULL) && + EvaluateExpressionList(OneOfOption->SuppressExpression, FALSE, NULL, NULL) > ExpressFalse) { + Index--; + continue; + } + } + + // + // Display the One of options + // + Index2 = Top + 1; + for (Index = TopOptionIndex; (Index < PopUpMenuLines) && (Index2 < Bottom); Index++) { + OneOfOption = QUESTION_OPTION_FROM_LINK (Link); + Link = GetNextNode (&Question->OptionListHead, Link); + + if (!OrderedList && (OneOfOption->SuppressExpression != NULL) && + EvaluateExpressionList(OneOfOption->SuppressExpression, FALSE, NULL, NULL) > ExpressFalse) { + Index--; + continue; + } + + StringPtr = GetToken (OneOfOption->Text, MenuOption->Handle); + ASSERT (StringPtr != NULL); + // + // If the string occupies multiple lines, truncate it to fit in one line, + // and append a "..." for indication. + // + if (StrLen (StringPtr) > (PopUpWidth - 1)) { + TempStringPtr = AllocateZeroPool (sizeof (CHAR16) * (PopUpWidth - 1)); + ASSERT ( TempStringPtr != NULL ); + CopyMem (TempStringPtr, StringPtr, (sizeof (CHAR16) * (PopUpWidth - 5))); + FreePool (StringPtr); + StringPtr = TempStringPtr; + StrCat (StringPtr, L"..."); + } + + if (Index == HighlightOptionIndex) { + // + // Highlight the selected one + // + CurrentOption = OneOfOption; + + gST->ConOut->SetAttribute (gST->ConOut, PICKLIST_HIGHLIGHT_TEXT | PICKLIST_HIGHLIGHT_BACKGROUND); + PrintStringAt (Start + 2, Index2, StringPtr); + gST->ConOut->SetAttribute (gST->ConOut, POPUP_TEXT | POPUP_BACKGROUND); + } else { + gST->ConOut->SetAttribute (gST->ConOut, POPUP_TEXT | POPUP_BACKGROUND); + PrintStringAt (Start + 2, Index2, StringPtr); + } + + Index2++; + FreePool (StringPtr); + } + + Character = BOXDRAW_UP_RIGHT; + PrintCharAt (Start, Bottom, Character); + for (Index = Start; Index + 2 < End; Index++) { + if ((ShowDownArrow) && ((Index + 1) == (Start + End) / 2)) { + Character = GEOMETRICSHAPE_DOWN_TRIANGLE; + } else { + Character = BOXDRAW_HORIZONTAL; + } + + PrintChar (Character); + } + + Character = BOXDRAW_UP_LEFT; + PrintChar (Character); + + // + // Get User selection + // + Key.UnicodeChar = CHAR_NULL; + if ((gDirection == SCAN_UP) || (gDirection == SCAN_DOWN)) { + Key.ScanCode = gDirection; + gDirection = 0; + goto TheKey; + } + + Status = WaitForKeyStroke (&Key); + +TheKey: + switch (Key.UnicodeChar) { + case '+': + if (OrderedList) { + if ((TopOptionIndex > 0) && (TopOptionIndex == HighlightOptionIndex)) { + // + // Highlight reaches the top of the popup window, scroll one menu item. + // + TopOptionIndex--; + ShowDownArrow = TRUE; + } + + if (TopOptionIndex == 0) { + ShowUpArrow = FALSE; + } + + if (HighlightOptionIndex > 0) { + HighlightOptionIndex--; + + ASSERT (CurrentOption != NULL); + SwapListEntries (CurrentOption->Link.BackLink, &CurrentOption->Link); + } + } + break; + + case '-': + // + // If an ordered list op-code, we will allow for a popup of +/- keys + // to create an ordered list of items + // + if (OrderedList) { + if (((TopOptionIndex + MenuLinesInView) < PopUpMenuLines) && + (HighlightOptionIndex == (TopOptionIndex + MenuLinesInView - 1))) { + // + // Highlight reaches the bottom of the popup window, scroll one menu item. + // + TopOptionIndex++; + ShowUpArrow = TRUE; + } + + if ((TopOptionIndex + MenuLinesInView) == PopUpMenuLines) { + ShowDownArrow = FALSE; + } + + if (HighlightOptionIndex < (PopUpMenuLines - 1)) { + HighlightOptionIndex++; + + ASSERT (CurrentOption != NULL); + SwapListEntries (&CurrentOption->Link, CurrentOption->Link.ForwardLink); + } + } + break; + + case CHAR_NULL: + switch (Key.ScanCode) { + case SCAN_UP: + case SCAN_DOWN: + if (Key.ScanCode == SCAN_UP) { + if ((TopOptionIndex > 0) && (TopOptionIndex == HighlightOptionIndex)) { + // + // Highlight reaches the top of the popup window, scroll one menu item. + // + TopOptionIndex--; + ShowDownArrow = TRUE; + } + + if (TopOptionIndex == 0) { + ShowUpArrow = FALSE; + } + + if (HighlightOptionIndex > 0) { + HighlightOptionIndex--; + } + } else { + if (((TopOptionIndex + MenuLinesInView) < PopUpMenuLines) && + (HighlightOptionIndex == (TopOptionIndex + MenuLinesInView - 1))) { + // + // Highlight reaches the bottom of the popup window, scroll one menu item. + // + TopOptionIndex++; + ShowUpArrow = TRUE; + } + + if ((TopOptionIndex + MenuLinesInView) == PopUpMenuLines) { + ShowDownArrow = FALSE; + } + + if (HighlightOptionIndex < (PopUpMenuLines - 1)) { + HighlightOptionIndex++; + } + } + break; + + case SCAN_ESC: + gST->ConOut->SetAttribute (gST->ConOut, SavedAttribute); + + // + // Restore link list order for orderedlist + // + if (OrderedList) { + HiiValue.Type = ValueType; + HiiValue.Value.u64 = 0; + for (Index = 0; Index < Question->MaxContainers; Index++) { + HiiValue.Value.u64 = GetArrayData (ValueArray, ValueType, Index); + if (HiiValue.Value.u64 == 0) { + break; + } + + OneOfOption = ValueToOption (Question, &HiiValue); + if (OneOfOption == NULL) { + return EFI_NOT_FOUND; + } + + RemoveEntryList (&OneOfOption->Link); + InsertTailList (&Question->OptionListHead, &OneOfOption->Link); + } + } + + return EFI_DEVICE_ERROR; + + default: + break; + } + + break; + + case CHAR_CARRIAGE_RETURN: + // + // return the current selection + // + if (OrderedList) { + Index = 0; + Link = GetFirstNode (&Question->OptionListHead); + while (!IsNull (&Question->OptionListHead, Link)) { + OneOfOption = QUESTION_OPTION_FROM_LINK (Link); + Link = GetNextNode (&Question->OptionListHead, Link); + + if ((OneOfOption->SuppressExpression != NULL) && + EvaluateExpressionList(OneOfOption->SuppressExpression, FALSE, NULL, NULL) != ExpressFalse) { + continue; + } + + SetArrayData (ValueArray, ValueType, Index, OneOfOption->Value.Value.u64); + + Index++; + if (Index > Question->MaxContainers) { + break; + } + } + } else { + ASSERT (CurrentOption != NULL); + CopyMem (&Question->HiiValue, &CurrentOption->Value, sizeof (EFI_HII_VALUE)); + } + + gST->ConOut->SetAttribute (gST->ConOut, SavedAttribute); + + Status = ValidateQuestion (Selection->FormSet, Selection->Form, Question, EFI_HII_EXPRESSION_INCONSISTENT_IF); + if (EFI_ERROR (Status)) { + // + // Input value is not valid, restore Question Value + // + GetQuestionValue (Selection->FormSet, Selection->Form, Question, GetSetValueWithEditBuffer); + } else { + SetQuestionValue (Selection->FormSet, Selection->Form, Question, GetSetValueWithEditBuffer); + UpdateStatusBar (Selection, NV_UPDATE_REQUIRED, Question->QuestionFlags, TRUE); + } + + return Status; + + default: + break; + } + } while (TRUE); + +} + +/** + Wait for a key to be pressed by user. + + @param Key The key which is pressed by user. + + @retval EFI_SUCCESS The function always completed successfully. + +**/ +EFI_STATUS +WaitForKeyStroke ( + OUT EFI_INPUT_KEY *Key + ) +{ + EFI_STATUS Status; + + while (TRUE) { + Status = gST->ConIn->ReadKeyStroke (gST->ConIn, Key); + if (!EFI_ERROR (Status)) { + break; + } + + if (Status != EFI_NOT_READY) { + continue; + } + + UiWaitForSingleEvent (gST->ConIn->WaitForKey, 0, 0); + } + return Status; +} diff --git a/MdeModulePkg/Universal/SetupBrowserDxe/Presentation.c b/MdeModulePkg/Universal/SetupBrowserDxe/Presentation.c index def18fd9f9..4cd71e5d44 100644 --- a/MdeModulePkg/Universal/SetupBrowserDxe/Presentation.c +++ b/MdeModulePkg/Universal/SetupBrowserDxe/Presentation.c @@ -19,1658 +19,863 @@ UI_MENU_SELECTION *gCurrentSelection; EFI_HII_HANDLE mCurrentHiiHandle = NULL; EFI_GUID mCurrentFormSetGuid = {0, 0, 0, {0, 0, 0, 0, 0, 0, 0, 0}}; UINT16 mCurrentFormId = 0; -EFI_EVENT mValueChangedEvent = NULL; -LIST_ENTRY mRefreshEventList = INITIALIZE_LIST_HEAD_VARIABLE (mRefreshEventList); -UINT32 gBrowserStatus = BROWSER_SUCCESS; -CHAR16 *gErrorInfo; -UINT16 mCurFakeQestId; -FORM_DISPLAY_ENGINE_FORM gDisplayFormData; /** - Evaluate all expressions in a Form. - - @param FormSet FormSet this Form belongs to. - @param Form The Form. - - @retval EFI_SUCCESS The expression evaluated successfuly - -**/ -EFI_STATUS -EvaluateFormExpressions ( - IN FORM_BROWSER_FORMSET *FormSet, - IN FORM_BROWSER_FORM *Form - ) -{ - EFI_STATUS Status; - LIST_ENTRY *Link; - FORM_EXPRESSION *Expression; - - Link = GetFirstNode (&Form->ExpressionListHead); - while (!IsNull (&Form->ExpressionListHead, Link)) { - Expression = FORM_EXPRESSION_FROM_LINK (Link); - Link = GetNextNode (&Form->ExpressionListHead, Link); - - if (Expression->Type == EFI_HII_EXPRESSION_INCONSISTENT_IF || - Expression->Type == EFI_HII_EXPRESSION_NO_SUBMIT_IF || - Expression->Type == EFI_HII_EXPRESSION_WRITE || - (Expression->Type == EFI_HII_EXPRESSION_READ && Form->FormType != STANDARD_MAP_FORM_TYPE)) { - // - // Postpone Form validation to Question editing or Form submitting or Question Write or Question Read for nonstandard form. - // - continue; - } - - Status = EvaluateExpression (FormSet, Form, Expression); - if (EFI_ERROR (Status)) { - return Status; - } - } - - return EFI_SUCCESS; -} - -/** - Add empty function for event process function. - - @param Event The Event need to be process - @param Context The context of the event. - -**/ -VOID -EFIAPI -SetupBrowserEmptyFunction ( - IN EFI_EVENT Event, - IN VOID *Context - ) -{ -} - -/** - Base on the opcode buffer info to get the display statement. - - @param OpCode The input opcode buffer for this statement. - - @retval Statement The statement use this opcode buffer. - -**/ -FORM_DISPLAY_ENGINE_STATEMENT * -GetDisplayStatement ( - IN EFI_IFR_OP_HEADER *OpCode - ) -{ - FORM_DISPLAY_ENGINE_STATEMENT *DisplayStatement; - LIST_ENTRY *Link; - - Link = GetFirstNode (&gDisplayFormData.StatementListHead); - while (!IsNull (&gDisplayFormData.StatementListHead, Link)) { - DisplayStatement = FORM_DISPLAY_ENGINE_STATEMENT_FROM_LINK (Link); - - if (DisplayStatement->OpCode == OpCode) { - return DisplayStatement; - } - Link = GetNextNode (&gDisplayFormData.StatementListHead, Link); - } - - return NULL; -} - -/** - Free the refresh event list. - -**/ -VOID -FreeRefreshEvent ( - VOID - ) -{ - LIST_ENTRY *Link; - FORM_BROWSER_REFRESH_EVENT_NODE *EventNode; - - while (!IsListEmpty (&mRefreshEventList)) { - Link = GetFirstNode (&mRefreshEventList); - EventNode = FORM_BROWSER_REFRESH_EVENT_FROM_LINK (Link); - RemoveEntryList (&EventNode->Link); - - gBS->CloseEvent (EventNode->RefreshEvent); - - FreePool (EventNode); - } -} - -/** - Check whether this statement value is changed. If yes, update the statement value and return TRUE; - else return FALSE. - - @param Statement The statement need to check. - -**/ -VOID -UpdateStatement ( - IN OUT FORM_BROWSER_STATEMENT *Statement - ) -{ - GetQuestionValue (gCurrentSelection->FormSet, gCurrentSelection->Form, Statement, GetSetValueWithHiiDriver); - - // - // Reset FormPackage update flag - // - mHiiPackageListUpdated = FALSE; - - // - // Question value may be changed, need invoke its Callback() - // - ProcessCallBackFunction (gCurrentSelection, Statement, EFI_BROWSER_ACTION_CHANGING, FALSE); - - if (mHiiPackageListUpdated) { - // - // Package list is updated, force to reparse IFR binary of target Formset - // - mHiiPackageListUpdated = FALSE; - gCurrentSelection->Action = UI_ACTION_REFRESH_FORMSET; - } -} - -/** - Refresh the question which has refresh guid event attribute. - - @param Event The event which has this function related. - @param Context The input context info related to this event or the status code return to the caller. -**/ -VOID -EFIAPI -RefreshEventNotify( - IN EFI_EVENT Event, - IN VOID *Context - ) -{ - FORM_BROWSER_STATEMENT *Statement; - - Statement = (FORM_BROWSER_STATEMENT *)Context; - UpdateStatement(Statement); - gBS->SignalEvent (mValueChangedEvent); -} - - -/** - Create refresh hook event for statement which has refresh event or interval. - - @param Statement The statement need to check. - -**/ -VOID -CreateRefreshEvent ( - IN FORM_BROWSER_STATEMENT *Statement - ) -{ - EFI_STATUS Status; - EFI_EVENT RefreshEvent; - FORM_BROWSER_REFRESH_EVENT_NODE *EventNode; - - // - // If question has refresh guid, create the notify function. - // - Status = gBS->CreateEventEx ( - EVT_NOTIFY_SIGNAL, - TPL_CALLBACK, - RefreshEventNotify, - Statement, - &Statement->RefreshGuid, - &RefreshEvent); - ASSERT_EFI_ERROR (Status); - - EventNode = AllocateZeroPool (sizeof (FORM_BROWSER_REFRESH_EVENT_NODE)); - ASSERT (EventNode != NULL); - EventNode->RefreshEvent = RefreshEvent; - InsertTailList(&mRefreshEventList, &EventNode->Link); -} - -/** - Perform value check for a question. - - @param Question The question need to do check. - @param ErrorInfo Return info about the error. - - @retval The check result. -**/ -UINT32 -InConsistentIfCheck ( - IN FORM_BROWSER_STATEMENT *Question, - OUT STATEMENT_ERROR_INFO *ErrorInfo - ) -{ - EFI_STATUS Status; - LIST_ENTRY *Link; - FORM_EXPRESSION *Expression; - LIST_ENTRY *ListHead; - UINT32 RetVal; - - RetVal = STATEMENT_VALID; - ListHead = &Question->InconsistentListHead; - - Link = GetFirstNode (ListHead); - while (!IsNull (ListHead, Link)) { - Expression = FORM_EXPRESSION_FROM_LINK (Link); - Link = GetNextNode (ListHead, Link); - - // - // Evaluate the expression - // - Status = EvaluateExpression (gCurrentSelection->FormSet, gCurrentSelection->Form, Expression); - if (EFI_ERROR (Status)) { - continue; - } - - if ((Expression->Result.Type == EFI_IFR_TYPE_BOOLEAN) && Expression->Result.Value.b) { - ErrorInfo->StringId = Expression->Error; - ErrorInfo->TimeOut = 0; - RetVal = INCOSISTENT_IF_TRUE; - break; - } - } - - return RetVal; -} - -/** - Perform value check for a question. - - @param Form Form where Statement is in. - @param Statement Value will check for it. - @param InputValue New value will be checked. - @param ErrorInfo Return the error info for this check. - - @retval TRUE Input Value is valid. - @retval FALSE Input Value is invalid. -**/ -UINT32 -EFIAPI -QuestionCheck ( - IN FORM_DISPLAY_ENGINE_FORM *Form, - IN FORM_DISPLAY_ENGINE_STATEMENT *Statement, - IN EFI_HII_VALUE *InputValue, - OUT STATEMENT_ERROR_INFO *ErrorInfo - ) -{ - FORM_BROWSER_STATEMENT *Question; - EFI_HII_VALUE BackUpValue; - UINT8 *BackUpBuffer; - UINT32 RetVal; - - BackUpBuffer = NULL; - RetVal = STATEMENT_VALID; - - ASSERT (Form != NULL && Statement != NULL && InputValue != NULL && ErrorInfo != NULL); - - Question = GetBrowserStatement(Statement); - ASSERT (Question != NULL); - - // - // Back up the quesion value. - // - switch (Question->Operand) { - case EFI_IFR_ORDERED_LIST_OP: - BackUpBuffer = AllocateCopyPool (Question->StorageWidth, Question->BufferValue); - ASSERT (BackUpBuffer != NULL); - CopyMem (Question->BufferValue, InputValue->Buffer, Question->StorageWidth); - break; - - default: - CopyMem (&BackUpValue, &Question->HiiValue, sizeof (EFI_HII_VALUE)); - CopyMem (&Question->HiiValue, InputValue, sizeof (EFI_HII_VALUE)); - break; - } - - // - // Do the inconsistentif check. - // - if (!IsListEmpty (&Question->InconsistentListHead)) { - RetVal = InConsistentIfCheck(Question, ErrorInfo); - } - - // - // Restore the quesion value. - // - switch (Question->Operand) { - case EFI_IFR_ORDERED_LIST_OP: - CopyMem (Question->BufferValue, BackUpBuffer, Question->StorageWidth); - break; - - default: - CopyMem (&Question->HiiValue, &BackUpValue, sizeof (EFI_HII_VALUE)); - break; - } - - return RetVal; -} - -/** - - Initialize the Display statement structure data. - - @param DisplayStatement Pointer to the display Statement data strucure. - @param Statement The statement need to check. - @param HostDisplayStatement Pointer to the display Statement data strucure which is an host statement. -**/ -VOID -InitializeDisplayStatement ( - IN OUT FORM_DISPLAY_ENGINE_STATEMENT *DisplayStatement, - IN FORM_BROWSER_STATEMENT *Statement, - IN FORM_DISPLAY_ENGINE_STATEMENT *HostDisplayStatement - ) -{ - LIST_ENTRY *Link; - QUESTION_OPTION *Option; - DISPLAY_QUESTION_OPTION *DisplayOption; - - DisplayStatement->Signature = FORM_DISPLAY_ENGINE_STATEMENT_SIGNATURE; - DisplayStatement->Version = FORM_DISPLAY_ENGINE_STATEMENT_VERSION_1; - DisplayStatement->OpCode = Statement->OpCode; - InitializeListHead (&DisplayStatement->NestStatementList); - InitializeListHead (&DisplayStatement->OptionListHead); - - if ((EvaluateExpressionList(Statement->Expression, FALSE, NULL, NULL) == ExpressGrayOut) || Statement->Locked) { - DisplayStatement->Attribute |= HII_DISPLAY_GRAYOUT; - } - if ((Statement->ValueExpression != NULL) || ((Statement->QuestionFlags & EFI_IFR_FLAG_READ_ONLY) != 0)) { - DisplayStatement->Attribute |= HII_DISPLAY_READONLY; - } - - // - // Initilize the option list in statement. - // - Link = GetFirstNode (&Statement->OptionListHead); - while (!IsNull (&Statement->OptionListHead, Link)) { - Option = QUESTION_OPTION_FROM_LINK (Link); - Link = GetNextNode (&Statement->OptionListHead, Link); - if ((Option->SuppressExpression != NULL) && - ((EvaluateExpressionList(Option->SuppressExpression, FALSE, NULL, NULL) == ExpressSuppress))) { - continue; - } - - DisplayOption = AllocateZeroPool (sizeof (DISPLAY_QUESTION_OPTION)); - ASSERT (DisplayOption != NULL); - - DisplayOption->ImageId = Option->ImageId; - DisplayOption->Signature = DISPLAY_QUESTION_OPTION_SIGNATURE; - DisplayOption->OptionOpCode = Option->OpCode; - InsertTailList(&DisplayStatement->OptionListHead, &DisplayOption->Link); - } - - CopyMem (&DisplayStatement->CurrentValue, &Statement->HiiValue, sizeof (EFI_HII_VALUE)); - - // - // Some special op code need an extra buffer to save the data. - // Such as string, password, orderedlist... - // - if (Statement->BufferValue != NULL) { - // - // Ordered list opcode may not initilized, get default value here. - // - if (Statement->OpCode->OpCode == EFI_IFR_ORDERED_LIST_OP && GetArrayData (Statement->BufferValue, Statement->ValueType, 0) == 0) { - GetQuestionDefault (gCurrentSelection->FormSet, gCurrentSelection->Form, Statement, 0); - } - - DisplayStatement->CurrentValue.Buffer = AllocateCopyPool(Statement->StorageWidth,Statement->BufferValue); - DisplayStatement->CurrentValue.BufferLen = Statement->StorageWidth; - } - - DisplayStatement->SettingChangedFlag = Statement->ValueChanged; - - // - // Get the highlight statement for current form. - // - if (((gCurrentSelection->QuestionId != 0) && (Statement->QuestionId == gCurrentSelection->QuestionId)) || - ((mCurFakeQestId != 0) && (Statement->FakeQuestionId == mCurFakeQestId))) { - gDisplayFormData.HighLightedStatement = DisplayStatement; - } - - // - // Create the refresh event process function. - // - if (!CompareGuid (&Statement->RefreshGuid, &gZeroGuid)) { - CreateRefreshEvent (Statement); - } - - // - // For RTC type of date/time, set default refresh interval to be 1 second. - // - if ((Statement->Operand == EFI_IFR_DATE_OP || Statement->Operand == EFI_IFR_TIME_OP) && Statement->Storage == NULL) { - Statement->RefreshInterval = 1; - } - - // - // Create the refresh guid hook event. - // If the statement in this form has refresh event or refresh interval, browser will create this event for display engine. - // - if ((!CompareGuid (&Statement->RefreshGuid, &gZeroGuid)) || (Statement->RefreshInterval != 0)) { - gDisplayFormData.FormRefreshEvent = mValueChangedEvent; - } - - // - // Save the password check function for later use. - // - if (Statement->Operand == EFI_IFR_PASSWORD_OP) { - DisplayStatement->PasswordCheck = PasswordCheck; - } - - // - // Save the validate check question for later use. - // - if (!IsListEmpty (&Statement->InconsistentListHead)) { - DisplayStatement->ValidateQuestion = QuestionCheck; - } - - // - // If this statement is nest in the subtitle, insert to the host statement. - // else insert to the form it belongs to. - // - if (Statement->InSubtitle) { - InsertTailList(&HostDisplayStatement->NestStatementList, &DisplayStatement->DisplayLink); - } else { - InsertTailList(&gDisplayFormData.StatementListHead, &DisplayStatement->DisplayLink); - } -} - -/** - Process for the refresh interval statement. - - @param Event The Event need to be process - @param Context The context of the event. - -**/ -VOID -EFIAPI -RefreshIntervalProcess ( - IN EFI_EVENT Event, - IN VOID *Context - ) -{ - FORM_BROWSER_STATEMENT *Statement; - LIST_ENTRY *Link; - - Link = GetFirstNode (&gCurrentSelection->Form->StatementListHead); - while (!IsNull (&gCurrentSelection->Form->StatementListHead, Link)) { - Statement = FORM_BROWSER_STATEMENT_FROM_LINK (Link); - Link = GetNextNode (&gCurrentSelection->Form->StatementListHead, Link); - - if (Statement->RefreshInterval == 0) { - continue; - } - - UpdateStatement(Statement); - } - - gBS->SignalEvent (mValueChangedEvent); -} - -/** - - Make a copy of the global hotkey info. - -**/ -VOID -UpdateHotkeyList ( - VOID - ) -{ - BROWSER_HOT_KEY *HotKey; - BROWSER_HOT_KEY *CopyKey; - LIST_ENTRY *Link; - - Link = GetFirstNode (&gBrowserHotKeyList); - while (!IsNull (&gBrowserHotKeyList, Link)) { - HotKey = BROWSER_HOT_KEY_FROM_LINK (Link); - - CopyKey = AllocateCopyPool(sizeof (BROWSER_HOT_KEY), HotKey); - CopyKey->KeyData = AllocateCopyPool(sizeof (EFI_INPUT_KEY), HotKey->KeyData); - CopyKey->HelpString = AllocateCopyPool(StrSize (HotKey->HelpString), HotKey->HelpString); - - InsertTailList(&gDisplayFormData.HotKeyListHead, &CopyKey->Link); - - Link = GetNextNode (&gBrowserHotKeyList, Link); - } -} - -/** - - Enum all statement in current form, find all the statement can be display and - add to the display form. - -**/ -VOID -AddStatementToDisplayForm ( - VOID - ) -{ - EFI_STATUS Status; - LIST_ENTRY *Link; - FORM_BROWSER_STATEMENT *Statement; - FORM_DISPLAY_ENGINE_STATEMENT *DisplayStatement; - FORM_DISPLAY_ENGINE_STATEMENT *HostDisplayStatement; - UINT8 MinRefreshInterval; - EFI_EVENT RefreshIntervalEvent; - FORM_BROWSER_REFRESH_EVENT_NODE *EventNode; - BOOLEAN FormEditable; - - HostDisplayStatement = NULL; - MinRefreshInterval = 0; - FormEditable = FALSE; - - // - // Process the statement outside the form, these statements are not recognized - // by browser core. - // - Link = GetFirstNode (&gCurrentSelection->FormSet->StatementListOSF); - while (!IsNull (&gCurrentSelection->FormSet->StatementListOSF, Link)) { - Statement = FORM_BROWSER_STATEMENT_FROM_LINK (Link); - Link = GetNextNode (&gCurrentSelection->FormSet->StatementListOSF, Link); - - DisplayStatement = AllocateZeroPool (sizeof (FORM_DISPLAY_ENGINE_STATEMENT)); - ASSERT (DisplayStatement != NULL); - DisplayStatement->Signature = FORM_DISPLAY_ENGINE_STATEMENT_SIGNATURE; - DisplayStatement->Version = FORM_DISPLAY_ENGINE_STATEMENT_VERSION_1; - DisplayStatement->OpCode = Statement->OpCode; - - InitializeListHead (&DisplayStatement->NestStatementList); - InitializeListHead (&DisplayStatement->OptionListHead); - - InsertTailList(&gDisplayFormData.StatementListOSF, &DisplayStatement->DisplayLink); - } - - // - // Process the statement in this form. - // - Link = GetFirstNode (&gCurrentSelection->Form->StatementListHead); - while (!IsNull (&gCurrentSelection->Form->StatementListHead, Link)) { - Statement = FORM_BROWSER_STATEMENT_FROM_LINK (Link); - Link = GetNextNode (&gCurrentSelection->Form->StatementListHead, Link); - - // - // This statement can't be show, skip it. - // - if (EvaluateExpressionList(Statement->Expression, FALSE, NULL, NULL) > ExpressGrayOut) { - continue; - } - - DisplayStatement = AllocateZeroPool (sizeof (FORM_DISPLAY_ENGINE_STATEMENT)); - ASSERT (DisplayStatement != NULL); - - // - // Initialize this statement and add it to the display form. - // - InitializeDisplayStatement(DisplayStatement, Statement, HostDisplayStatement); - - // - // Save the Host statement info. - // Host statement may has nest statement follow it. - // - if (!Statement->InSubtitle) { - HostDisplayStatement = DisplayStatement; - } - - if (Statement->Storage != NULL) { - FormEditable = TRUE; - } - - // - // Get the minimal refresh interval value for later use. - // - if ((Statement->RefreshInterval != 0) && - (MinRefreshInterval == 0 || Statement->RefreshInterval < MinRefreshInterval)) { - MinRefreshInterval = Statement->RefreshInterval; - } - } - - // - // Create the periodic timer for refresh interval statement. - // - if (MinRefreshInterval != 0) { - Status = gBS->CreateEvent (EVT_TIMER | EVT_NOTIFY_SIGNAL, TPL_CALLBACK, RefreshIntervalProcess, NULL, &RefreshIntervalEvent); - ASSERT_EFI_ERROR (Status); - Status = gBS->SetTimer (RefreshIntervalEvent, TimerPeriodic, MinRefreshInterval * ONE_SECOND); - ASSERT_EFI_ERROR (Status); - - EventNode = AllocateZeroPool (sizeof (FORM_BROWSER_REFRESH_EVENT_NODE)); - ASSERT (EventNode != NULL); - EventNode->RefreshEvent = RefreshIntervalEvent; - InsertTailList(&mRefreshEventList, &EventNode->Link); - } - - // - // Update hotkey list field. - // - if (gBrowserSettingScope == SystemLevel || FormEditable) { - UpdateHotkeyList(); - } -} - -/** - - Initialize the SettingChangedFlag variable in the display form. - -**/ -VOID -UpdateDataChangedFlag ( - VOID - ) -{ - LIST_ENTRY *Link; - FORM_BROWSER_FORMSET *LocalFormSet; - - gDisplayFormData.SettingChangedFlag = FALSE; - - if (IsNvUpdateRequiredForForm (gCurrentSelection->Form)) { - gDisplayFormData.SettingChangedFlag = TRUE; - return; - } - - // - // Base on the system level to check whether need to show the NV flag. - // - switch (gBrowserSettingScope) { - case SystemLevel: - // - // Check the maintain list to see whether there is any change. - // - Link = GetFirstNode (&gBrowserFormSetList); - while (!IsNull (&gBrowserFormSetList, Link)) { - LocalFormSet = FORM_BROWSER_FORMSET_FROM_LINK (Link); - if (IsNvUpdateRequiredForFormSet(LocalFormSet)) { - gDisplayFormData.SettingChangedFlag = TRUE; - return; - } - Link = GetNextNode (&gBrowserFormSetList, Link); - } - break; - - case FormSetLevel: - if (IsNvUpdateRequiredForFormSet(gCurrentSelection->FormSet)) { - gDisplayFormData.SettingChangedFlag = TRUE; - return; - } - break; - - default: - break; - } -} - -/** - - Initialize the Display form structure data. - -**/ -VOID -InitializeDisplayFormData ( - VOID - ) -{ - EFI_STATUS Status; - - gDisplayFormData.Signature = FORM_DISPLAY_ENGINE_FORM_SIGNATURE; - gDisplayFormData.Version = FORM_DISPLAY_ENGINE_VERSION_1; - gDisplayFormData.ImageId = 0; - gDisplayFormData.AnimationId = 0; - - InitializeListHead (&gDisplayFormData.StatementListHead); - InitializeListHead (&gDisplayFormData.StatementListOSF); - InitializeListHead (&gDisplayFormData.HotKeyListHead); - - Status = gBS->CreateEvent ( - EVT_NOTIFY_WAIT, - TPL_CALLBACK, - SetupBrowserEmptyFunction, - NULL, - &mValueChangedEvent - ); - ASSERT_EFI_ERROR (Status); -} - -/** - - Free the kotkey info saved in form data. - -**/ -VOID -FreeHotkeyList ( - VOID - ) -{ - BROWSER_HOT_KEY *HotKey; - LIST_ENTRY *Link; - - while (!IsListEmpty (&gDisplayFormData.HotKeyListHead)) { - Link = GetFirstNode (&gDisplayFormData.HotKeyListHead); - HotKey = BROWSER_HOT_KEY_FROM_LINK (Link); - - RemoveEntryList (&HotKey->Link); - - FreePool (HotKey->KeyData); - FreePool (HotKey->HelpString); - FreePool (HotKey); - } -} - -/** - - Update the Display form structure data. - -**/ -VOID -UpdateDisplayFormData ( - VOID - ) -{ - gDisplayFormData.FormTitle = gCurrentSelection->Form->FormTitle; - gDisplayFormData.FormId = gCurrentSelection->FormId; - gDisplayFormData.HiiHandle = gCurrentSelection->Handle; - CopyGuid (&gDisplayFormData.FormSetGuid, &gCurrentSelection->FormSetGuid); - - gDisplayFormData.Attribute = 0; - gDisplayFormData.Attribute |= gCurrentSelection->Form->ModalForm ? HII_DISPLAY_MODAL : 0; - gDisplayFormData.Attribute |= gCurrentSelection->Form->Locked ? HII_DISPLAY_LOCK : 0; - - gDisplayFormData.FormRefreshEvent = NULL; - gDisplayFormData.HighLightedStatement = NULL; - - gDisplayFormData.BrowserStatus = gBrowserStatus; - gDisplayFormData.ErrorString = gErrorInfo; - - gBrowserStatus = BROWSER_SUCCESS; - gErrorInfo = NULL; - - UpdateDataChangedFlag (); - - AddStatementToDisplayForm (); -} - -/** - - Free the Display Statement structure data. - - @param StatementList Point to the statement list which need to be free. - -**/ -VOID -FreeStatementData ( - LIST_ENTRY *StatementList - ) -{ - LIST_ENTRY *Link; - LIST_ENTRY *OptionLink; - FORM_DISPLAY_ENGINE_STATEMENT *Statement; - DISPLAY_QUESTION_OPTION *Option; - - // - // Free Statements/Questions - // - while (!IsListEmpty (StatementList)) { - Link = GetFirstNode (StatementList); - Statement = FORM_DISPLAY_ENGINE_STATEMENT_FROM_LINK (Link); - - // - // Free Options List - // - while (!IsListEmpty (&Statement->OptionListHead)) { - OptionLink = GetFirstNode (&Statement->OptionListHead); - Option = DISPLAY_QUESTION_OPTION_FROM_LINK (OptionLink); - RemoveEntryList (&Option->Link); - FreePool (Option); - } + Clear retangle with specified text attribute. - // - // Free nest statement List - // - if (!IsListEmpty (&Statement->NestStatementList)) { - FreeStatementData(&Statement->NestStatementList); - } - - RemoveEntryList (&Statement->DisplayLink); - FreePool (Statement); - } -} - -/** - - Free the Display form structure data. + @param LeftColumn Left column of retangle. + @param RightColumn Right column of retangle. + @param TopRow Start row of retangle. + @param BottomRow End row of retangle. + @param TextAttribute The character foreground and background. **/ VOID -FreeDisplayFormData ( - VOID - ) -{ - FreeStatementData (&gDisplayFormData.StatementListHead); - FreeStatementData (&gDisplayFormData.StatementListOSF); - - FreeRefreshEvent(); - - FreeHotkeyList(); -} - -/** - - Get FORM_BROWSER_STATEMENT from FORM_DISPLAY_ENGINE_STATEMENT based on the OpCode info. - - @param DisplayStatement The input FORM_DISPLAY_ENGINE_STATEMENT. - - @retval FORM_BROWSER_STATEMENT The return FORM_BROWSER_STATEMENT info. - -**/ -FORM_BROWSER_STATEMENT * -GetBrowserStatement ( - IN FORM_DISPLAY_ENGINE_STATEMENT *DisplayStatement - ) -{ - FORM_BROWSER_STATEMENT *Statement; - LIST_ENTRY *Link; - - Link = GetFirstNode (&gCurrentSelection->Form->StatementListHead); - while (!IsNull (&gCurrentSelection->Form->StatementListHead, Link)) { - Statement = FORM_BROWSER_STATEMENT_FROM_LINK (Link); - - if (Statement->OpCode == DisplayStatement->OpCode) { - return Statement; - } - - Link = GetNextNode (&gCurrentSelection->Form->StatementListHead, Link); - } - - return NULL; -} - -/** - - Process the action request in user input. - - @param Action The user input action request info. - @param DefaultId The user input default Id info. - - @retval EFI_SUCESSS This function always return successfully for now. - -**/ -EFI_STATUS -ProcessAction ( - IN UINT32 Action, - IN UINT16 DefaultId - ) -{ - EFI_STATUS Status; - - // - // This is caused by use press ESC, and it should not combine with other action type. - // - if ((Action & BROWSER_ACTION_FORM_EXIT) == BROWSER_ACTION_FORM_EXIT) { - FindNextMenu (gCurrentSelection, FormLevel); - return EFI_SUCCESS; - } - - // - // Below is normal hotkey trigged action, these action maybe combine with each other. - // - if ((Action & BROWSER_ACTION_DISCARD) == BROWSER_ACTION_DISCARD) { - DiscardForm (gCurrentSelection->FormSet, gCurrentSelection->Form, gBrowserSettingScope); - } - - if ((Action & BROWSER_ACTION_DEFAULT) == BROWSER_ACTION_DEFAULT) { - ExtractDefault (gCurrentSelection->FormSet, gCurrentSelection->Form, DefaultId, gBrowserSettingScope, GetDefaultForAll, NULL, FALSE); - } - - if ((Action & BROWSER_ACTION_SUBMIT) == BROWSER_ACTION_SUBMIT) { - Status = SubmitForm (gCurrentSelection->FormSet, gCurrentSelection->Form, gBrowserSettingScope); - if (EFI_ERROR (Status)) { - gBrowserStatus = BROWSER_SUBMIT_FAIL; - } - } - - if ((Action & BROWSER_ACTION_RESET) == BROWSER_ACTION_RESET) { - gResetRequired = TRUE; - } - - if ((Action & BROWSER_ACTION_EXIT) == BROWSER_ACTION_EXIT) { - // - // Form Exit without saving, Similar to ESC Key. - // FormSet Exit without saving, Exit SendForm. - // System Exit without saving, CallExitHandler and Exit SendForm. - // - DiscardForm (gCurrentSelection->FormSet, gCurrentSelection->Form, gBrowserSettingScope); - if (gBrowserSettingScope == FormLevel || gBrowserSettingScope == FormSetLevel) { - FindNextMenu (gCurrentSelection, gBrowserSettingScope); - } else if (gBrowserSettingScope == SystemLevel) { - if (ExitHandlerFunction != NULL) { - ExitHandlerFunction (); - } - gCurrentSelection->Action = UI_ACTION_EXIT; - } - } - - return EFI_SUCCESS; -} - - -/** - Find HII Handle in the HII database associated with given Device Path. - - If DevicePath is NULL, then ASSERT. - - @param DevicePath Device Path associated with the HII package list - handle. - - @retval Handle HII package list Handle associated with the Device - Path. - @retval NULL Hii Package list handle is not found. - -**/ -EFI_HII_HANDLE -EFIAPI -DevicePathToHiiHandle ( - IN EFI_DEVICE_PATH_PROTOCOL *DevicePath +ClearLines ( + IN UINTN LeftColumn, + IN UINTN RightColumn, + IN UINTN TopRow, + IN UINTN BottomRow, + IN UINTN TextAttribute ) { - EFI_STATUS Status; - EFI_DEVICE_PATH_PROTOCOL *TmpDevicePath; - UINTN BufferSize; - UINTN HandleCount; - UINTN Index; - EFI_HANDLE Handle; - EFI_HANDLE DriverHandle; - EFI_HII_HANDLE *HiiHandles; - EFI_HII_HANDLE HiiHandle; - - ASSERT (DevicePath != NULL); - - TmpDevicePath = DevicePath; - // - // Locate Device Path Protocol handle buffer - // - Status = gBS->LocateDevicePath ( - &gEfiDevicePathProtocolGuid, - &TmpDevicePath, - &DriverHandle - ); - if (EFI_ERROR (Status) || !IsDevicePathEnd (TmpDevicePath)) { - return NULL; - } - - // - // Retrieve all HII Handles from HII database - // - BufferSize = 0x1000; - HiiHandles = AllocatePool (BufferSize); - ASSERT (HiiHandles != NULL); - Status = mHiiDatabase->ListPackageLists ( - mHiiDatabase, - EFI_HII_PACKAGE_TYPE_ALL, - NULL, - &BufferSize, - HiiHandles - ); - if (Status == EFI_BUFFER_TOO_SMALL) { - FreePool (HiiHandles); - HiiHandles = AllocatePool (BufferSize); - ASSERT (HiiHandles != NULL); - - Status = mHiiDatabase->ListPackageLists ( - mHiiDatabase, - EFI_HII_PACKAGE_TYPE_ALL, - NULL, - &BufferSize, - HiiHandles - ); - } - - if (EFI_ERROR (Status)) { - FreePool (HiiHandles); - return NULL; - } + CHAR16 *Buffer; + UINTN Row; // - // Search Hii Handle by Driver Handle + // For now, allocate an arbitrarily long buffer // - HiiHandle = NULL; - HandleCount = BufferSize / sizeof (EFI_HII_HANDLE); - for (Index = 0; Index < HandleCount; Index++) { - Status = mHiiDatabase->GetPackageListHandle ( - mHiiDatabase, - HiiHandles[Index], - &Handle - ); - if (!EFI_ERROR (Status) && (Handle == DriverHandle)) { - HiiHandle = HiiHandles[Index]; - break; - } - } - - FreePool (HiiHandles); - return HiiHandle; -} - -/** - Find HII Handle in the HII database associated with given form set guid. - - If FormSetGuid is NULL, then ASSERT. - - @param ComparingGuid FormSet Guid associated with the HII package list - handle. + Buffer = AllocateZeroPool (0x10000); + ASSERT (Buffer != NULL); - @retval Handle HII package list Handle associated with the Device - Path. - @retval NULL Hii Package list handle is not found. - -**/ -EFI_HII_HANDLE -FormSetGuidToHiiHandle ( - EFI_GUID *ComparingGuid - ) -{ - EFI_HII_HANDLE *HiiHandles; - UINTN Index; - EFI_HII_PACKAGE_LIST_HEADER *HiiPackageList; - UINTN BufferSize; - UINT32 Offset; - UINT32 Offset2; - UINT32 PackageListLength; - EFI_HII_PACKAGE_HEADER PackageHeader; - UINT8 *Package; - UINT8 *OpCodeData; - EFI_STATUS Status; - EFI_HII_HANDLE HiiHandle; - - ASSERT (ComparingGuid != NULL); - - HiiHandle = NULL; // - // Get all the Hii handles + // Set foreground and background as defined // - HiiHandles = HiiGetHiiHandles (NULL); - ASSERT (HiiHandles != NULL); + gST->ConOut->SetAttribute (gST->ConOut, TextAttribute); // - // Search for formset of each class type + // Much faster to buffer the long string instead of print it a character at a time // - for (Index = 0; HiiHandles[Index] != NULL; Index++) { - BufferSize = 0; - HiiPackageList = NULL; - Status = mHiiDatabase->ExportPackageLists (mHiiDatabase, HiiHandles[Index], &BufferSize, HiiPackageList); - if (Status == EFI_BUFFER_TOO_SMALL) { - HiiPackageList = AllocatePool (BufferSize); - ASSERT (HiiPackageList != NULL); - - Status = mHiiDatabase->ExportPackageLists (mHiiDatabase, HiiHandles[Index], &BufferSize, HiiPackageList); - } - if (EFI_ERROR (Status) || HiiPackageList == NULL) { - return NULL; - } - - // - // Get Form package from this HII package List - // - Offset = sizeof (EFI_HII_PACKAGE_LIST_HEADER); - Offset2 = 0; - CopyMem (&PackageListLength, &HiiPackageList->PackageLength, sizeof (UINT32)); - - while (Offset < PackageListLength) { - Package = ((UINT8 *) HiiPackageList) + Offset; - CopyMem (&PackageHeader, Package, sizeof (EFI_HII_PACKAGE_HEADER)); - - if (PackageHeader.Type == EFI_HII_PACKAGE_FORMS) { - // - // Search FormSet in this Form Package - // - Offset2 = sizeof (EFI_HII_PACKAGE_HEADER); - while (Offset2 < PackageHeader.Length) { - OpCodeData = Package + Offset2; - - if (((EFI_IFR_OP_HEADER *) OpCodeData)->OpCode == EFI_IFR_FORM_SET_OP) { - // - // Try to compare against formset GUID - // - if (CompareGuid (ComparingGuid, (EFI_GUID *)(OpCodeData + sizeof (EFI_IFR_OP_HEADER)))) { - HiiHandle = HiiHandles[Index]; - break; - } - } - - Offset2 += ((EFI_IFR_OP_HEADER *) OpCodeData)->Length; - } - } - if (HiiHandle != NULL) { - break; - } - Offset += PackageHeader.Length; - } - - FreePool (HiiPackageList); - if (HiiHandle != NULL) { - break; - } + SetUnicodeMem (Buffer, RightColumn - LeftColumn, L' '); + + // + // Clear the desired area with the appropriate foreground/background + // + for (Row = TopRow; Row <= BottomRow; Row++) { + PrintStringAt (LeftColumn, Row, Buffer); } - FreePool (HiiHandles); + gST->ConOut->SetCursorPosition (gST->ConOut, LeftColumn, TopRow); - return HiiHandle; + FreePool (Buffer); + return ; } /** - check how to process the changed data in current form or form set. - - @param Selection On input, Selection tell setup browser the information - about the Selection, form and formset to be displayed. - On output, Selection return the screen item that is selected - by user. + Concatenate a narrow string to another string. - @param Scope Data save or discard scope, form or formset. + @param Destination The destination string. + @param Source The source string. The string to be concatenated. + to the end of Destination. - @retval TRUE Success process the changed data, will return to the parent form. - @retval FALSE Reject to process the changed data, will stay at current form. **/ -BOOLEAN -ProcessChangedData ( - IN OUT UI_MENU_SELECTION *Selection, - IN BROWSER_SETTING_SCOPE Scope +VOID +NewStrCat ( + IN OUT CHAR16 *Destination, + IN CHAR16 *Source ) { - BOOLEAN RetValue; - - RetValue = TRUE; - switch (mFormDisplay->ConfirmDataChange()) { - case BROWSER_ACTION_DISCARD: - DiscardForm (Selection->FormSet, Selection->Form, Scope); - break; - - case BROWSER_ACTION_SUBMIT: - SubmitForm (Selection->FormSet, Selection->Form, Scope); - break; + UINTN Length; - case BROWSER_ACTION_NONE: - RetValue = FALSE; - break; + for (Length = 0; Destination[Length] != 0; Length++) + ; - default: - // - // if Invalid value return, process same as BROWSER_ACTION_NONE. - // - RetValue = FALSE; - break; - } + // + // We now have the length of the original string + // We can safely assume for now that we are concatenating a narrow value to this string. + // For instance, the string is "XYZ" and cat'ing ">" + // If this assumption changes, we need to make this routine a bit more complex + // + Destination[Length] = NARROW_CHAR; + Length++; - return RetValue; + StrCpy (Destination + Length, Source); } /** - Find parent formset menu(the first menu which has different formset) for current menu. - If not find, just return to the first menu. + Count the storage space of a Unicode string. + + This function handles the Unicode string with NARROW_CHAR + and WIDE_CHAR control characters. NARROW_HCAR and WIDE_CHAR + does not count in the resultant output. If a WIDE_CHAR is + hit, then 2 Unicode character will consume an output storage + space with size of CHAR16 till a NARROW_CHAR is hit. + + If String is NULL, then ASSERT (). + + @param String The input string to be counted. - @param Selection The selection info. + @return Storage space for the input string. **/ -VOID -FindParentFormSet ( - IN OUT UI_MENU_SELECTION *Selection +UINTN +GetStringWidth ( + IN CHAR16 *String ) { - FORM_ENTRY_INFO *CurrentMenu; - FORM_ENTRY_INFO *ParentMenu; + UINTN Index; + UINTN Count; + UINTN IncrementValue; - CurrentMenu = Selection->CurrentMenu; - ParentMenu = UiFindParentMenu(CurrentMenu); + ASSERT (String != NULL); + if (String == NULL) { + return 0; + } + + Index = 0; + Count = 0; + IncrementValue = 1; + + do { + // + // Advance to the null-terminator or to the first width directive + // + for (; + (String[Index] != NARROW_CHAR) && (String[Index] != WIDE_CHAR) && (String[Index] != 0); + Index++, Count = Count + IncrementValue + ) + ; + + // + // We hit the null-terminator, we now have a count + // + if (String[Index] == 0) { + break; + } + // + // We encountered a narrow directive - strip it from the size calculation since it doesn't get printed + // and also set the flag that determines what we increment by.(if narrow, increment by 1, if wide increment by 2) + // + if (String[Index] == NARROW_CHAR) { + // + // Skip to the next character + // + Index++; + IncrementValue = 1; + } else { + // + // Skip to the next character + // + Index++; + IncrementValue = 2; + } + } while (String[Index] != 0); // - // Find a menu which has different formset guid with current. + // Increment by one to include the null-terminator in the size // - while (ParentMenu != NULL && CompareGuid (&CurrentMenu->FormSetGuid, &ParentMenu->FormSetGuid)) { - CurrentMenu = ParentMenu; - ParentMenu = UiFindParentMenu(CurrentMenu); - } - - if (ParentMenu != NULL) { - CopyMem (&Selection->FormSetGuid, &ParentMenu->FormSetGuid, sizeof (EFI_GUID)); - Selection->Handle = ParentMenu->HiiHandle; - Selection->FormId = ParentMenu->FormId; - Selection->QuestionId = ParentMenu->QuestionId; - } else { - Selection->FormId = CurrentMenu->FormId; - Selection->QuestionId = CurrentMenu->QuestionId; - } + Count++; - Selection->Statement = NULL; + return Count * sizeof (CHAR16); } /** - Process the goto op code, update the info in the selection structure. + This function displays the page frame. - @param Statement The statement belong to goto op code. - @param Selection The selection info. - - @retval EFI_SUCCESS The menu process successfully. - @return Other value if the process failed. + @param Selection Selection contains the information about + the Selection, form and formset to be displayed. + Selection action may be updated in retrieve callback. **/ -EFI_STATUS -ProcessGotoOpCode ( - IN OUT FORM_BROWSER_STATEMENT *Statement, - IN OUT UI_MENU_SELECTION *Selection +VOID +DisplayPageFrame ( + IN UI_MENU_SELECTION *Selection ) { - CHAR16 *StringPtr; - EFI_DEVICE_PATH_PROTOCOL *DevicePath; - FORM_BROWSER_FORM *RefForm; - EFI_STATUS Status; - EFI_HII_HANDLE HiiHandle; - - Status = EFI_SUCCESS; - StringPtr = NULL; - HiiHandle = NULL; - - // - // Prepare the device path check, get the device path info first. - // - if (Statement->HiiValue.Value.ref.DevicePath != 0) { - StringPtr = GetToken (Statement->HiiValue.Value.ref.DevicePath, Selection->FormSet->HiiHandle); + UINTN Index; + UINT8 Line; + UINT8 Alignment; + CHAR16 Character; + CHAR16 *Buffer; + CHAR16 *StrFrontPageBanner; + UINTN Row; + EFI_SCREEN_DESCRIPTOR LocalScreen; + UINT8 RowIdx; + UINT8 ColumnIdx; + + ZeroMem (&LocalScreen, sizeof (EFI_SCREEN_DESCRIPTOR)); + gST->ConOut->QueryMode (gST->ConOut, gST->ConOut->Mode->Mode, &LocalScreen.RightColumn, &LocalScreen.BottomRow); + ClearLines (0, LocalScreen.RightColumn, 0, LocalScreen.BottomRow, KEYHELP_BACKGROUND); + + if (Selection->Form->ModalForm) { + return; } + CopyMem (&LocalScreen, &gScreenDimensions, sizeof (EFI_SCREEN_DESCRIPTOR)); + // - // Check whether the device path string is a valid string. + // For now, allocate an arbitrarily long buffer // - if (Statement->HiiValue.Value.ref.DevicePath != 0 && StringPtr != NULL) { - if (Selection->Form->ModalForm) { - return Status; - } + Buffer = AllocateZeroPool (0x10000); + ASSERT (Buffer != NULL); + + Character = BOXDRAW_HORIZONTAL; + + for (Index = 0; Index + 2 < (LocalScreen.RightColumn - LocalScreen.LeftColumn); Index++) { + Buffer[Index] = Character; + } + if ((gClassOfVfr & FORMSET_CLASS_FRONT_PAGE) == FORMSET_CLASS_FRONT_PAGE) { // - // Goto another Hii Package list + // ClearLines(0, LocalScreen.RightColumn, 0, BANNER_HEIGHT-1, BANNER_TEXT | BANNER_BACKGROUND); // - if (mPathFromText != NULL) { - DevicePath = mPathFromText->ConvertTextToDevicePath(StringPtr); - if (DevicePath != NULL) { - HiiHandle = DevicePathToHiiHandle (DevicePath); - FreePool (DevicePath); - } - FreePool (StringPtr); - } else { + ClearLines ( + LocalScreen.LeftColumn, + LocalScreen.RightColumn, + LocalScreen.TopRow, + FRONT_PAGE_HEADER_HEIGHT - 1 + LocalScreen.TopRow, + BANNER_TEXT | BANNER_BACKGROUND + ); + // + // for (Line = 0; Line < BANNER_HEIGHT; Line++) { + // + for (Line = (UINT8) LocalScreen.TopRow; Line < BANNER_HEIGHT + (UINT8) LocalScreen.TopRow; Line++) { // - // Not found the EFI_DEVICE_PATH_FROM_TEXT_PROTOCOL protocol. + // for (Alignment = 0; Alignment < BANNER_COLUMNS; Alignment++) { // - gBrowserStatus = BROWSER_PROTOCOL_NOT_FOUND; - FreePool (StringPtr); - return Status; - } + for (Alignment = (UINT8) LocalScreen.LeftColumn; + Alignment < BANNER_COLUMNS + (UINT8) LocalScreen.LeftColumn; + Alignment++ + ) { + RowIdx = (UINT8) (Line - (UINT8) LocalScreen.TopRow); + ColumnIdx = (UINT8) (Alignment - (UINT8) LocalScreen.LeftColumn); + + ASSERT (RowIdx < BANNER_HEIGHT); + ASSERT (ColumnIdx < BANNER_COLUMNS); + + if (gBannerData->Banner[RowIdx][ColumnIdx] != 0x0000) { + StrFrontPageBanner = GetToken ( + gBannerData->Banner[RowIdx][ColumnIdx], + gFrontPageHandle + ); + } else { + continue; + } - if (HiiHandle != Selection->Handle) { - // - // Goto another Formset, check for uncommitted data - // - if ((gBrowserSettingScope == FormLevel || gBrowserSettingScope == FormSetLevel) && - IsNvUpdateRequiredForFormSet(Selection->FormSet)) { - if (!ProcessChangedData(Selection, FormSetLevel)) { - return EFI_SUCCESS; + switch (Alignment - LocalScreen.LeftColumn) { + case 0: + // + // Handle left column + // + PrintStringAt (LocalScreen.LeftColumn + BANNER_LEFT_COLUMN_INDENT, Line, StrFrontPageBanner); + break; + + case 1: + // + // Handle center column + // + PrintStringAt ( + LocalScreen.LeftColumn + (LocalScreen.RightColumn - LocalScreen.LeftColumn) / 3, + Line, + StrFrontPageBanner + ); + break; + + case 2: + // + // Handle right column + // + PrintStringAt ( + LocalScreen.LeftColumn + (LocalScreen.RightColumn - LocalScreen.LeftColumn) * 2 / 3, + Line, + StrFrontPageBanner + ); + break; } + + FreePool (StrFrontPageBanner); } } + } - Selection->Action = UI_ACTION_REFRESH_FORMSET; - Selection->Handle = HiiHandle; - if (Selection->Handle == NULL) { - // - // If target Hii Handle not found, exit current formset. - // - FindParentFormSet(Selection); - return EFI_SUCCESS; + ClearLines ( + LocalScreen.LeftColumn, + LocalScreen.RightColumn, + LocalScreen.BottomRow - STATUS_BAR_HEIGHT - gFooterHeight, + LocalScreen.BottomRow - STATUS_BAR_HEIGHT - 1, + KEYHELP_TEXT | KEYHELP_BACKGROUND + ); + + if ((gClassOfVfr & FORMSET_CLASS_FRONT_PAGE) != FORMSET_CLASS_FRONT_PAGE) { + ClearLines ( + LocalScreen.LeftColumn, + LocalScreen.RightColumn, + LocalScreen.TopRow, + LocalScreen.TopRow + NONE_FRONT_PAGE_HEADER_HEIGHT - 1, + TITLE_TEXT | TITLE_BACKGROUND + ); + // + // Print Top border line + // +------------------------------------------------------------------------------+ + // ? ? + // +------------------------------------------------------------------------------+ + // + Character = BOXDRAW_DOWN_RIGHT; + + PrintChar (Character); + PrintString (Buffer); + + Character = BOXDRAW_DOWN_LEFT; + PrintChar (Character); + + Character = BOXDRAW_VERTICAL; + for (Row = LocalScreen.TopRow + 1; Row <= LocalScreen.TopRow + NONE_FRONT_PAGE_HEADER_HEIGHT - 2; Row++) { + PrintCharAt (LocalScreen.LeftColumn, Row, Character); + PrintCharAt (LocalScreen.RightColumn - 1, Row, Character); } - CopyMem (&Selection->FormSetGuid,&Statement->HiiValue.Value.ref.FormSetGuid, sizeof (EFI_GUID)); - Selection->FormId = Statement->HiiValue.Value.ref.FormId; - Selection->QuestionId = Statement->HiiValue.Value.ref.QuestionId; - } else if (!CompareGuid (&Statement->HiiValue.Value.ref.FormSetGuid, &gZeroGuid)) { - if (Selection->Form->ModalForm) { - return Status; - } - if (!CompareGuid (&Statement->HiiValue.Value.ref.FormSetGuid, &Selection->FormSetGuid)) { + Character = BOXDRAW_UP_RIGHT; + PrintCharAt (LocalScreen.LeftColumn, LocalScreen.TopRow + NONE_FRONT_PAGE_HEADER_HEIGHT - 1, Character); + PrintString (Buffer); + + Character = BOXDRAW_UP_LEFT; + PrintChar (Character); + + if ((gClassOfVfr & FORMSET_CLASS_PLATFORM_SETUP) == FORMSET_CLASS_PLATFORM_SETUP) { // - // Goto another Formset, check for uncommitted data + // Print Bottom border line + // +------------------------------------------------------------------------------+ + // ? ? + // +------------------------------------------------------------------------------+ // - if ((gBrowserSettingScope == FormLevel || gBrowserSettingScope == FormSetLevel) && - IsNvUpdateRequiredForFormSet(Selection->FormSet)) { - if (!ProcessChangedData(Selection, FormSetLevel)) { - return EFI_SUCCESS; - } + Character = BOXDRAW_DOWN_RIGHT; + PrintCharAt (LocalScreen.LeftColumn, LocalScreen.BottomRow - STATUS_BAR_HEIGHT - gFooterHeight, Character); + + PrintString (Buffer); + + Character = BOXDRAW_DOWN_LEFT; + PrintChar (Character); + Character = BOXDRAW_VERTICAL; + for (Row = LocalScreen.BottomRow - STATUS_BAR_HEIGHT - gFooterHeight + 1; + Row <= LocalScreen.BottomRow - STATUS_BAR_HEIGHT - 2; + Row++ + ) { + PrintCharAt (LocalScreen.LeftColumn, Row, Character); + PrintCharAt (LocalScreen.RightColumn - 1, Row, Character); } - } - Selection->Action = UI_ACTION_REFRESH_FORMSET; - Selection->Handle = FormSetGuidToHiiHandle(&Statement->HiiValue.Value.ref.FormSetGuid); - if (Selection->Handle == NULL) { - // - // If target Hii Handle not found, exit current formset. - // - FindParentFormSet(Selection); - return EFI_SUCCESS; - } + Character = BOXDRAW_UP_RIGHT; + PrintCharAt (LocalScreen.LeftColumn, LocalScreen.BottomRow - STATUS_BAR_HEIGHT - 1, Character); - CopyMem (&Selection->FormSetGuid, &Statement->HiiValue.Value.ref.FormSetGuid, sizeof (EFI_GUID)); - Selection->FormId = Statement->HiiValue.Value.ref.FormId; - Selection->QuestionId = Statement->HiiValue.Value.ref.QuestionId; - } else if (Statement->HiiValue.Value.ref.FormId != 0) { - // - // Goto another Form, check for uncommitted data - // - if (Statement->HiiValue.Value.ref.FormId != Selection->FormId) { - if ((gBrowserSettingScope == FormLevel && IsNvUpdateRequiredForForm(Selection->Form))) { - if (!ProcessChangedData (Selection, FormLevel)) { - return EFI_SUCCESS; - } - } - } + PrintString (Buffer); - RefForm = IdToForm (Selection->FormSet, Statement->HiiValue.Value.ref.FormId); - if ((RefForm != NULL) && (RefForm->SuppressExpression != NULL)) { - if (EvaluateExpressionList(RefForm->SuppressExpression, TRUE, Selection->FormSet, RefForm) != ExpressFalse) { - // - // Form is suppressed. - // - gBrowserStatus = BROWSER_FORM_SUPPRESS; - return EFI_SUCCESS; - } + Character = BOXDRAW_UP_LEFT; + PrintChar (Character); } - - Selection->FormId = Statement->HiiValue.Value.ref.FormId; - Selection->QuestionId = Statement->HiiValue.Value.ref.QuestionId; - } else if (Statement->HiiValue.Value.ref.QuestionId != 0) { - Selection->QuestionId = Statement->HiiValue.Value.ref.QuestionId; } - return Status; + FreePool (Buffer); + } /** - Process Question Config. + Evaluate all expressions in a Form. - @param Selection The UI menu selection. - @param Question The Question to be peocessed. + @param FormSet FormSet this Form belongs to. + @param Form The Form. - @retval EFI_SUCCESS Question Config process success. - @retval Other Question Config process fail. + @retval EFI_SUCCESS The expression evaluated successfuly **/ EFI_STATUS -ProcessQuestionConfig ( - IN UI_MENU_SELECTION *Selection, - IN FORM_BROWSER_STATEMENT *Question +EvaluateFormExpressions ( + IN FORM_BROWSER_FORMSET *FormSet, + IN FORM_BROWSER_FORM *Form ) { - EFI_STATUS Status; - CHAR16 *ConfigResp; - CHAR16 *Progress; - EFI_HII_CONFIG_ACCESS_PROTOCOL *ConfigAccess; + EFI_STATUS Status; + LIST_ENTRY *Link; + FORM_EXPRESSION *Expression; - if (Question->QuestionConfig == 0) { - return EFI_SUCCESS; - } + Link = GetFirstNode (&Form->ExpressionListHead); + while (!IsNull (&Form->ExpressionListHead, Link)) { + Expression = FORM_EXPRESSION_FROM_LINK (Link); + Link = GetNextNode (&Form->ExpressionListHead, Link); - // - // Get - // - ConfigResp = GetToken (Question->QuestionConfig, Selection->FormSet->HiiHandle); - if (ConfigResp == NULL) { - return EFI_NOT_FOUND; - } + if (Expression->Type == EFI_HII_EXPRESSION_INCONSISTENT_IF || + Expression->Type == EFI_HII_EXPRESSION_NO_SUBMIT_IF || + Expression->Type == EFI_HII_EXPRESSION_WRITE || + (Expression->Type == EFI_HII_EXPRESSION_READ && Form->FormType != STANDARD_MAP_FORM_TYPE)) { + // + // Postpone Form validation to Question editing or Form submitting or Question Write or Question Read for nonstandard form. + // + continue; + } - // - // Send config to Configuration Driver - // - ConfigAccess = Selection->FormSet->ConfigAccess; - if (ConfigAccess == NULL) { - return EFI_UNSUPPORTED; + Status = EvaluateExpression (FormSet, Form, Expression); + if (EFI_ERROR (Status)) { + return Status; + } } - Status = ConfigAccess->RouteConfig ( - ConfigAccess, - ConfigResp, - &Progress - ); - return Status; + return EFI_SUCCESS; } +/* ++------------------------------------------------------------------------------+ +? Setup Page ? ++------------------------------------------------------------------------------+ + + + + + + + + + + + + + + + + + ++------------------------------------------------------------------------------+ +?F1=Scroll Help F9=Reset to Defaults F10=Save and Exit ? +| ^"=Move Highlight Toggles Checkbox Esc=Discard Changes | ++------------------------------------------------------------------------------+ +*/ + /** - Process the user input data. - @param UserInput The user input data. - @param ChangeHighlight Whether need to change the highlight statement. + Display form and wait for user to select one menu option, then return it. + @param Selection On input, Selection tell setup browser the information + about the Selection, form and formset to be displayed. + On output, Selection return the screen item that is selected + by user. @retval EFI_SUCESSS This function always return successfully for now. **/ EFI_STATUS -ProcessUserInput ( - IN USER_INPUT *UserInput, - IN BOOLEAN ChangeHighlight +DisplayForm ( + IN OUT UI_MENU_SELECTION *Selection ) { - EFI_STATUS Status; - FORM_BROWSER_STATEMENT *Statement; + CHAR16 *StringPtr; + UINT16 MenuItemCount; + EFI_HII_HANDLE Handle; + EFI_SCREEN_DESCRIPTOR LocalScreen; + UINT16 Width; + UINTN ArrayEntry; + CHAR16 *OutputString; + LIST_ENTRY *Link; + FORM_BROWSER_STATEMENT *Statement; + UINT16 NumberOfLines; + EFI_STATUS Status; + UI_MENU_OPTION *MenuOption; + UINT16 GlyphWidth; - Status = EFI_SUCCESS; + Handle = Selection->Handle; + MenuItemCount = 0; + ArrayEntry = 0; + OutputString = NULL; - // - // When Exit from FormDisplay function, one of the below two cases must be true. - // - ASSERT (UserInput->Action != 0 || UserInput->SelectedStatement != NULL); + UiInitMenu (); + + CopyMem (&LocalScreen, &gScreenDimensions, sizeof (EFI_SCREEN_DESCRIPTOR)); + + StringPtr = GetToken (Selection->Form->FormTitle, Handle); + + if ((gClassOfVfr & FORMSET_CLASS_FRONT_PAGE) != FORMSET_CLASS_FRONT_PAGE) { + if (Selection->Form->ModalForm) { + gST->ConOut->SetAttribute (gST->ConOut, TITLE_TEXT | EFI_BACKGROUND_BLACK); + } else { + gST->ConOut->SetAttribute (gST->ConOut, TITLE_TEXT | TITLE_BACKGROUND); + } + PrintStringAt ( + (LocalScreen.RightColumn + LocalScreen.LeftColumn - GetStringWidth (StringPtr) / 2) / 2, + LocalScreen.TopRow + 1, + StringPtr + ); + } // - // Remove the last highligh question id, this id will update when show next form. + // Remove Buffer allocated for StringPtr after it has been used. // - gCurrentSelection->QuestionId = 0; + FreePool (StringPtr); // - // First process the Action field in USER_INPUT. + // Evaluate all the Expressions in this Form // - if (UserInput->Action != 0) { - Status = ProcessAction (UserInput->Action, UserInput->DefaultId); - if (EFI_ERROR (Status)) { - return Status; - } + Status = EvaluateFormExpressions (Selection->FormSet, Selection->Form); + if (EFI_ERROR (Status)) { + return Status; + } - // - // Clear the highlight info. - // - gCurrentSelection->Statement = NULL; + Selection->FormEditable = FALSE; + Link = GetFirstNode (&Selection->Form->StatementListHead); + while (!IsNull (&Selection->Form->StatementListHead, Link)) { + Statement = FORM_BROWSER_STATEMENT_FROM_LINK (Link); - if (UserInput->SelectedStatement != NULL) { - Statement = GetBrowserStatement(UserInput->SelectedStatement); - ASSERT (Statement != NULL); - // - // Save the current highlight menu in the menu history data. - // which will be used when later browse back to this form. - // - gCurrentSelection->CurrentMenu->QuestionId = Statement->QuestionId; - // - // For statement like text, actio, it not has question id. - // So use FakeQuestionId to save the question. - // - if (gCurrentSelection->CurrentMenu->QuestionId == 0) { - mCurFakeQestId = Statement->FakeQuestionId; - } else { - mCurFakeQestId = 0; - } - } - } else { - Statement = GetBrowserStatement(UserInput->SelectedStatement); - ASSERT (Statement != NULL); + if (EvaluateExpressionList(Statement->Expression, FALSE, NULL, NULL) <= ExpressGrayOut) { + StringPtr = GetToken (Statement->Prompt, Handle); + ASSERT (StringPtr != NULL); - gCurrentSelection->Statement = Statement; + Width = GetWidth (Statement, Handle); - if (ChangeHighlight) { - // - // This question is the current user select one,record it and later - // show it as the highlight question. - // - gCurrentSelection->CurrentMenu->QuestionId = Statement->QuestionId; - // - // For statement like text, actio, it not has question id. - // So use FakeQuestionId to save the question. - // - if (gCurrentSelection->CurrentMenu->QuestionId == 0) { - mCurFakeQestId = Statement->FakeQuestionId; - } else { - mCurFakeQestId = 0; + NumberOfLines = 1; + ArrayEntry = 0; + GlyphWidth = 1; + for (; GetLineByWidth (StringPtr, Width, &GlyphWidth,&ArrayEntry, &OutputString) != 0x0000;) { + // + // If there is more string to process print on the next row and increment the Skip value + // + if (StrLen (&StringPtr[ArrayEntry]) != 0) { + NumberOfLines++; + } + + FreePool (OutputString); } - } - switch (Statement->Operand) { - case EFI_IFR_REF_OP: - Status = ProcessGotoOpCode(Statement, gCurrentSelection); - break; - - case EFI_IFR_ACTION_OP: - // - // Process the Config string - // - Status = ProcessQuestionConfig (gCurrentSelection, Statement); - break; - - case EFI_IFR_RESET_BUTTON_OP: // - // Reset Question to default value specified by DefaultId + // We are NOT!! removing this StringPtr buffer via FreePool since it is being used in the menuoptions, we will do + // it in UiFreeMenu. // - Status = ExtractDefault (gCurrentSelection->FormSet, NULL, Statement->DefaultId, FormSetLevel, GetDefaultForAll, NULL, FALSE); - break; - - default: - switch (Statement->Operand) { - case EFI_IFR_STRING_OP: - DeleteString(Statement->HiiValue.Value.string, gCurrentSelection->FormSet->HiiHandle); - Statement->HiiValue.Value.string = UserInput->InputValue.Value.string; - CopyMem (Statement->BufferValue, UserInput->InputValue.Buffer, (UINTN) UserInput->InputValue.BufferLen); - FreePool (UserInput->InputValue.Buffer); - break; - - case EFI_IFR_PASSWORD_OP: - if (UserInput->InputValue.Buffer == NULL) { - // - // User not input new password, just return. - // - break; - } + MenuOption = UiAddMenuOption (StringPtr, Selection->Handle, Selection->Form, Statement, NumberOfLines, MenuItemCount); + MenuItemCount++; - DeleteString(Statement->HiiValue.Value.string, gCurrentSelection->FormSet->HiiHandle); - Statement->HiiValue.Value.string = UserInput->InputValue.Value.string; - CopyMem (Statement->BufferValue, UserInput->InputValue.Buffer, (UINTN) UserInput->InputValue.BufferLen); - FreePool (UserInput->InputValue.Buffer); + if (MenuOption->IsQuestion && !MenuOption->ReadOnly) { // - // Two password match, send it to Configuration Driver + // At least one item is not readonly, this Form is considered as editable // - if ((Statement->QuestionFlags & EFI_IFR_FLAG_CALLBACK) != 0) { - PasswordCheck (NULL, UserInput->SelectedStatement, (CHAR16 *) Statement->BufferValue); - // - // Clean the value after saved it. - // - ZeroMem (Statement->BufferValue, (UINTN) UserInput->InputValue.BufferLen); - HiiSetString (gCurrentSelection->FormSet->HiiHandle, Statement->HiiValue.Value.string, (CHAR16*)Statement->BufferValue, NULL); - } else { - SetQuestionValue (gCurrentSelection->FormSet, gCurrentSelection->Form, Statement, GetSetValueWithHiiDriver); - } - break; - - case EFI_IFR_ORDERED_LIST_OP: - CopyMem (Statement->BufferValue, UserInput->InputValue.Buffer, UserInput->InputValue.BufferLen); - break; - - default: - CopyMem (&Statement->HiiValue, &UserInput->InputValue, sizeof (EFI_HII_VALUE)); - break; - } - if (Statement->Operand != EFI_IFR_PASSWORD_OP) { - SetQuestionValue (gCurrentSelection->FormSet, gCurrentSelection->Form, Statement, GetSetValueWithEditBuffer); + Selection->FormEditable = TRUE; } - break; } + + Link = GetNextNode (&Selection->Form->StatementListHead, Link); } + Status = UiDisplayMenu (Selection); + + UiFreeMenu (); + return Status; } /** + Initialize the HII String Token to the correct values. + +**/ +VOID +InitializeBrowserStrings ( + VOID + ) +{ + gEnterString = GetToken (STRING_TOKEN (ENTER_STRING), gHiiHandle); + gEnterCommitString = GetToken (STRING_TOKEN (ENTER_COMMIT_STRING), gHiiHandle); + gEnterEscapeString = GetToken (STRING_TOKEN (ENTER_ESCAPE_STRING), gHiiHandle); + gEscapeString = GetToken (STRING_TOKEN (ESCAPE_STRING), gHiiHandle); + gMoveHighlight = GetToken (STRING_TOKEN (MOVE_HIGHLIGHT), gHiiHandle); + gMakeSelection = GetToken (STRING_TOKEN (MAKE_SELECTION), gHiiHandle); + gDecNumericInput = GetToken (STRING_TOKEN (DEC_NUMERIC_INPUT), gHiiHandle); + gHexNumericInput = GetToken (STRING_TOKEN (HEX_NUMERIC_INPUT), gHiiHandle); + gToggleCheckBox = GetToken (STRING_TOKEN (TOGGLE_CHECK_BOX), gHiiHandle); + gPromptForData = GetToken (STRING_TOKEN (PROMPT_FOR_DATA), gHiiHandle); + gPromptForPassword = GetToken (STRING_TOKEN (PROMPT_FOR_PASSWORD), gHiiHandle); + gPromptForNewPassword = GetToken (STRING_TOKEN (PROMPT_FOR_NEW_PASSWORD), gHiiHandle); + gConfirmPassword = GetToken (STRING_TOKEN (CONFIRM_PASSWORD), gHiiHandle); + gConfirmError = GetToken (STRING_TOKEN (CONFIRM_ERROR), gHiiHandle); + gPassowordInvalid = GetToken (STRING_TOKEN (PASSWORD_INVALID), gHiiHandle); + gPressEnter = GetToken (STRING_TOKEN (PRESS_ENTER), gHiiHandle); + gEmptyString = GetToken (STRING_TOKEN (EMPTY_STRING), gHiiHandle); + gAreYouSure = GetToken (STRING_TOKEN (ARE_YOU_SURE), gHiiHandle); + gYesResponse = GetToken (STRING_TOKEN (ARE_YOU_SURE_YES), gHiiHandle); + gNoResponse = GetToken (STRING_TOKEN (ARE_YOU_SURE_NO), gHiiHandle); + gMiniString = GetToken (STRING_TOKEN (MINI_STRING), gHiiHandle); + gPlusString = GetToken (STRING_TOKEN (PLUS_STRING), gHiiHandle); + gMinusString = GetToken (STRING_TOKEN (MINUS_STRING), gHiiHandle); + gAdjustNumber = GetToken (STRING_TOKEN (ADJUST_NUMBER), gHiiHandle); + gSaveChanges = GetToken (STRING_TOKEN (SAVE_CHANGES), gHiiHandle); + gOptionMismatch = GetToken (STRING_TOKEN (OPTION_MISMATCH), gHiiHandle); + gFormSuppress = GetToken (STRING_TOKEN (FORM_SUPPRESSED), gHiiHandle); + gProtocolNotFound = GetToken (STRING_TOKEN (PROTOCOL_NOT_FOUND), gHiiHandle); + return ; +} + +/** + Free up the resource allocated for all strings required + by Setup Browser. - Display form and wait for user to select one menu option, then return it. +**/ +VOID +FreeBrowserStrings ( + VOID + ) +{ + FreePool (gEnterString); + FreePool (gEnterCommitString); + FreePool (gEnterEscapeString); + FreePool (gEscapeString); + FreePool (gMoveHighlight); + FreePool (gMakeSelection); + FreePool (gDecNumericInput); + FreePool (gHexNumericInput); + FreePool (gToggleCheckBox); + FreePool (gPromptForData); + FreePool (gPromptForPassword); + FreePool (gPromptForNewPassword); + FreePool (gConfirmPassword); + FreePool (gPassowordInvalid); + FreePool (gConfirmError); + FreePool (gPressEnter); + FreePool (gEmptyString); + FreePool (gAreYouSure); + FreePool (gYesResponse); + FreePool (gNoResponse); + FreePool (gMiniString); + FreePool (gPlusString); + FreePool (gMinusString); + FreePool (gAdjustNumber); + FreePool (gSaveChanges); + FreePool (gOptionMismatch); + FreePool (gFormSuppress); + FreePool (gProtocolNotFound); + return ; +} - @retval EFI_SUCESSS This function always return successfully for now. +/** + Show all registered HotKey help strings on bottom Rows. **/ -EFI_STATUS -DisplayForm ( +VOID +PrintHotKeyHelpString ( VOID ) { - EFI_STATUS Status; - USER_INPUT UserInput; - FORM_ENTRY_INFO *CurrentMenu; - BOOLEAN ChangeHighlight; + UINTN CurrentCol; + UINTN CurrentRow; + UINTN BottomRowOfHotKeyHelp; + UINTN ColumnWidth; + UINTN Index; + EFI_SCREEN_DESCRIPTOR LocalScreen; + LIST_ENTRY *Link; + BROWSER_HOT_KEY *HotKey; - ZeroMem (&UserInput, sizeof (USER_INPUT)); + CopyMem (&LocalScreen, &gScreenDimensions, sizeof (EFI_SCREEN_DESCRIPTOR)); + ColumnWidth = (LocalScreen.RightColumn - LocalScreen.LeftColumn) / 3; + BottomRowOfHotKeyHelp = LocalScreen.BottomRow - STATUS_BAR_HEIGHT - 3; // - // Update the menu history data. + // Calculate total number of Register HotKeys. // - CurrentMenu = UiFindMenuList (gCurrentSelection->Handle, &gCurrentSelection->FormSetGuid, gCurrentSelection->FormId); - if (CurrentMenu == NULL) { + Index = 0; + Link = GetFirstNode (&gBrowserHotKeyList); + while (!IsNull (&gBrowserHotKeyList, Link)) { + HotKey = BROWSER_HOT_KEY_FROM_LINK (Link); // - // Current menu not found, add it to the menu tree + // Help string can't exceed ColumnWidth. One Row will show three Help information. // - CurrentMenu = UiAddMenuList (gCurrentSelection->Handle, &gCurrentSelection->FormSetGuid, - gCurrentSelection->FormId, gCurrentSelection->QuestionId); - ASSERT (CurrentMenu != NULL); - } - gCurrentSelection->CurrentMenu = CurrentMenu; + if (StrLen (HotKey->HelpString) > ColumnWidth) { + HotKey->HelpString[ColumnWidth] = L'\0'; + } + // + // Calculate help information Column and Row. + // + if ((Index % 3) != 2) { + CurrentCol = LocalScreen.LeftColumn + (2 - Index % 3) * ColumnWidth; + } else { + CurrentCol = LocalScreen.LeftColumn + 2; + } + CurrentRow = BottomRowOfHotKeyHelp - Index / 3; + // + // Print HotKey help string on bottom Row. + // + PrintStringAt (CurrentCol, CurrentRow, HotKey->HelpString); - // - // Find currrent highlight statement. - // - if (gCurrentSelection->QuestionId == 0) { // - // Highlight not specified, fetch it from cached menu + // Get Next Hot Key. // - gCurrentSelection->QuestionId = CurrentMenu->QuestionId; + Link = GetNextNode (&gBrowserHotKeyList, Link); + Index ++; } + + return; +} - // - // Evaluate all the Expressions in this Form - // - Status = EvaluateFormExpressions (gCurrentSelection->FormSet, gCurrentSelection->Form); - if (EFI_ERROR (Status)) { - return Status; - } +/** + Update key's help imformation. - UpdateDisplayFormData (); + @param Selection Tell setup browser the information about the Selection + @param MenuOption The Menu option + @param Selected Whether or not a tag be selected - // - // Three possible status maybe return. - // - // EFI_INVALID_PARAMETER: The input dimension info is not valid. - // EFI_NOT_FOUND: The input value for oneof/orderedlist opcode is not valid - // and an valid value has return. - // EFI_SUCCESS: Success shows form and get user input in UserInput paramenter. - // - Status = mFormDisplay->FormDisplay (&gDisplayFormData, &UserInput); - if (EFI_ERROR (Status) && Status != EFI_NOT_FOUND) { - FreeDisplayFormData(); - return Status; +**/ +VOID +UpdateKeyHelp ( + IN UI_MENU_SELECTION *Selection, + IN UI_MENU_OPTION *MenuOption, + IN BOOLEAN Selected + ) +{ + UINTN SecCol; + UINTN ThdCol; + UINTN LeftColumnOfHelp; + UINTN RightColumnOfHelp; + UINTN TopRowOfHelp; + UINTN BottomRowOfHelp; + UINTN StartColumnOfHelp; + EFI_SCREEN_DESCRIPTOR LocalScreen; + FORM_BROWSER_STATEMENT *Statement; + + gST->ConOut->SetAttribute (gST->ConOut, KEYHELP_TEXT | KEYHELP_BACKGROUND); + + if (Selection->Form->ModalForm) { + return; } - // - // If status is EFI_SUCCESS, means user has change the highlight menu and new user input return. - // in this case, browser need to change the highlight menu. - // If status is EFI_NOT_FOUND, means the input DisplayFormData has error for oneof/orderedlist - // opcode and new valid value has return, browser core need to adjust - // value for this opcode and shows this form again. - // - ChangeHighlight = (Status == EFI_SUCCESS ? TRUE :FALSE); + CopyMem (&LocalScreen, &gScreenDimensions, sizeof (EFI_SCREEN_DESCRIPTOR)); - Status = ProcessUserInput (&UserInput, ChangeHighlight); + SecCol = LocalScreen.LeftColumn + (LocalScreen.RightColumn - LocalScreen.LeftColumn) / 3; + ThdCol = LocalScreen.LeftColumn + (LocalScreen.RightColumn - LocalScreen.LeftColumn) / 3 * 2; - FreeDisplayFormData(); + StartColumnOfHelp = LocalScreen.LeftColumn + 2; + LeftColumnOfHelp = LocalScreen.LeftColumn + 1; + RightColumnOfHelp = LocalScreen.RightColumn - 2; + TopRowOfHelp = LocalScreen.BottomRow - STATUS_BAR_HEIGHT - gFooterHeight + 1; + BottomRowOfHelp = LocalScreen.BottomRow - STATUS_BAR_HEIGHT - 2; - return Status; + Statement = MenuOption->ThisTag; + switch (Statement->Operand) { + case EFI_IFR_ORDERED_LIST_OP: + case EFI_IFR_ONE_OF_OP: + case EFI_IFR_NUMERIC_OP: + case EFI_IFR_TIME_OP: + case EFI_IFR_DATE_OP: + ClearLines (LeftColumnOfHelp, RightColumnOfHelp, TopRowOfHelp, BottomRowOfHelp, KEYHELP_TEXT | KEYHELP_BACKGROUND); + + if (!Selected) { + // + // On system setting, HotKey will show on every form. + // + if (gBrowserSettingScope == SystemLevel || + (Selection->FormEditable && gFunctionKeySetting != NONE_FUNCTION_KEY_SETTING)) { + PrintHotKeyHelpString (); + } + + if ((gClassOfVfr & FORMSET_CLASS_PLATFORM_SETUP) == FORMSET_CLASS_PLATFORM_SETUP) { + PrintStringAt (ThdCol, BottomRowOfHelp, gEscapeString); + } + + if ((Statement->Operand == EFI_IFR_DATE_OP) || + (Statement->Operand == EFI_IFR_TIME_OP)) { + PrintAt ( + StartColumnOfHelp, + BottomRowOfHelp, + L"%c%c%c%c%s", + ARROW_UP, + ARROW_DOWN, + ARROW_RIGHT, + ARROW_LEFT, + gMoveHighlight + ); + PrintStringAt (SecCol, BottomRowOfHelp, gEnterString); + PrintStringAt (StartColumnOfHelp, TopRowOfHelp, gAdjustNumber); + } else { + PrintAt (StartColumnOfHelp, BottomRowOfHelp, L"%c%c%s", ARROW_UP, ARROW_DOWN, gMoveHighlight); + if (Statement->Operand == EFI_IFR_NUMERIC_OP && Statement->Step != 0) { + PrintStringAt (StartColumnOfHelp, TopRowOfHelp, gAdjustNumber); + } + PrintStringAt (SecCol, BottomRowOfHelp, gEnterString); + } + } else { + PrintStringAt (SecCol, BottomRowOfHelp, gEnterCommitString); + + // + // If it is a selected numeric with manual input, display different message + // + if ((Statement->Operand == EFI_IFR_NUMERIC_OP) || + (Statement->Operand == EFI_IFR_DATE_OP) || + (Statement->Operand == EFI_IFR_TIME_OP)) { + PrintStringAt ( + SecCol, + TopRowOfHelp, + ((Statement->Flags & EFI_IFR_DISPLAY_UINT_HEX) == EFI_IFR_DISPLAY_UINT_HEX) ? gHexNumericInput : gDecNumericInput + ); + } else if (Statement->Operand != EFI_IFR_ORDERED_LIST_OP) { + PrintAt (StartColumnOfHelp, BottomRowOfHelp, L"%c%c%s", ARROW_UP, ARROW_DOWN, gMoveHighlight); + } + + if (Statement->Operand == EFI_IFR_ORDERED_LIST_OP) { + PrintStringAt (StartColumnOfHelp, TopRowOfHelp, gPlusString); + PrintStringAt (ThdCol, TopRowOfHelp, gMinusString); + } + + PrintStringAt (ThdCol, BottomRowOfHelp, gEnterEscapeString); + } + break; + + case EFI_IFR_CHECKBOX_OP: + ClearLines (LeftColumnOfHelp, RightColumnOfHelp, TopRowOfHelp, BottomRowOfHelp, KEYHELP_TEXT | KEYHELP_BACKGROUND); + + // + // On system setting, HotKey will show on every form. + // + if (gBrowserSettingScope == SystemLevel || + (Selection->FormEditable && gFunctionKeySetting != NONE_FUNCTION_KEY_SETTING)) { + PrintHotKeyHelpString (); + } + if ((gClassOfVfr & FORMSET_CLASS_PLATFORM_SETUP) == FORMSET_CLASS_PLATFORM_SETUP) { + PrintStringAt (ThdCol, BottomRowOfHelp, gEscapeString); + } + + PrintAt (StartColumnOfHelp, BottomRowOfHelp, L"%c%c%s", ARROW_UP, ARROW_DOWN, gMoveHighlight); + PrintStringAt (SecCol, BottomRowOfHelp, gToggleCheckBox); + break; + + case EFI_IFR_REF_OP: + case EFI_IFR_PASSWORD_OP: + case EFI_IFR_STRING_OP: + case EFI_IFR_TEXT_OP: + case EFI_IFR_ACTION_OP: + case EFI_IFR_RESET_BUTTON_OP: + case EFI_IFR_SUBTITLE_OP: + ClearLines (LeftColumnOfHelp, RightColumnOfHelp, TopRowOfHelp, BottomRowOfHelp, KEYHELP_TEXT | KEYHELP_BACKGROUND); + + if (!Selected) { + // + // On system setting, HotKey will show on every form. + // + if (gBrowserSettingScope == SystemLevel || + (Selection->FormEditable && gFunctionKeySetting != NONE_FUNCTION_KEY_SETTING)) { + PrintHotKeyHelpString (); + } + if ((gClassOfVfr & FORMSET_CLASS_PLATFORM_SETUP) == FORMSET_CLASS_PLATFORM_SETUP) { + PrintStringAt (ThdCol, BottomRowOfHelp, gEscapeString); + } + + PrintAt (StartColumnOfHelp, BottomRowOfHelp, L"%c%c%s", ARROW_UP, ARROW_DOWN, gMoveHighlight); + if (Statement->Operand != EFI_IFR_TEXT_OP && Statement->Operand != EFI_IFR_SUBTITLE_OP) { + PrintStringAt (SecCol, BottomRowOfHelp, gEnterString); + } + } else { + if (Statement->Operand != EFI_IFR_REF_OP) { + PrintStringAt ( + (LocalScreen.RightColumn - GetStringWidth (gEnterCommitString) / 2) / 2, + BottomRowOfHelp, + gEnterCommitString + ); + PrintStringAt (ThdCol, BottomRowOfHelp, gEnterEscapeString); + } + } + break; + + default: + break; + } } /** @@ -1715,136 +920,60 @@ FormUpdateNotify ( } /** - Update the NV flag info for this form set. + check whether the formset need to update the NV. @param FormSet FormSet data structure. + @retval TRUE Need to update the NV. + @retval FALSE No need to update the NV. **/ -BOOLEAN -IsNvUpdateRequiredForFormSet ( +BOOLEAN +IsNvUpdateRequired ( IN FORM_BROWSER_FORMSET *FormSet ) { LIST_ENTRY *Link; FORM_BROWSER_FORM *Form; - BOOLEAN RetVal; - - // - // Not finished question initialization, return FALSE. - // - if (!FormSet->QuestionInited) { - return FALSE; - } - - RetVal = FALSE; Link = GetFirstNode (&FormSet->FormListHead); while (!IsNull (&FormSet->FormListHead, Link)) { Form = FORM_BROWSER_FORM_FROM_LINK (Link); - RetVal = IsNvUpdateRequiredForForm(Form); - if (RetVal) { - break; - } - - Link = GetNextNode (&FormSet->FormListHead, Link); - } - - return RetVal; -} - -/** - Update the NvUpdateRequired flag for a form. - - @param Form Form data structure. - -**/ -BOOLEAN -IsNvUpdateRequiredForForm ( - IN FORM_BROWSER_FORM *Form - ) -{ - LIST_ENTRY *Link; - FORM_BROWSER_STATEMENT *Statement; - - Link = GetFirstNode (&Form->StatementListHead); - while (!IsNull (&Form->StatementListHead, Link)) { - Statement = FORM_BROWSER_STATEMENT_FROM_LINK (Link); - - if (Statement->ValueChanged) { + if (Form->NvUpdateRequired ) { return TRUE; } - Link = GetNextNode (&Form->StatementListHead, Link); + Link = GetNextNode (&FormSet->FormListHead, Link); } return FALSE; } /** - Check whether the storage data for current form set is changed. + check whether the formset need to update the NV. - @param FormSet FormSet data structure. + @param FormSet FormSet data structure. + @param SetValue Whether set new value or clear old value. - @retval TRUE Data is changed. - @retval FALSE Data is not changed. **/ -BOOLEAN -IsStorageDataChangedForFormSet ( - IN FORM_BROWSER_FORMSET *FormSet +VOID +UpdateNvInfoInForm ( + IN FORM_BROWSER_FORMSET *FormSet, + IN BOOLEAN SetValue ) { LIST_ENTRY *Link; - FORMSET_STORAGE *Storage; - BROWSER_STORAGE *BrowserStorage; - CHAR16 *ConfigRespNew; - CHAR16 *ConfigRespOld; - BOOLEAN RetVal; - - RetVal = FALSE; - ConfigRespNew = NULL; - ConfigRespOld = NULL; - - // - // Request current settings from Configuration Driver - // - Link = GetFirstNode (&FormSet->StorageListHead); - while (!IsNull (&FormSet->StorageListHead, Link)) { - Storage = FORMSET_STORAGE_FROM_LINK (Link); - Link = GetNextNode (&FormSet->StorageListHead, Link); - - BrowserStorage = Storage->BrowserStorage; - - if (BrowserStorage->Type == EFI_HII_VARSTORE_EFI_VARIABLE) { - continue; - } - - if (Storage->ElementCount == 0) { - continue; - } - - StorageToConfigResp (BrowserStorage, &ConfigRespNew, Storage->ConfigRequest, TRUE); - StorageToConfigResp (BrowserStorage, &ConfigRespOld, Storage->ConfigRequest, FALSE); - ASSERT (ConfigRespNew != NULL && ConfigRespOld != NULL); - - if (StrCmp (ConfigRespNew, ConfigRespOld) != 0) { - RetVal = TRUE; - } - - FreePool (ConfigRespNew); - ConfigRespNew = NULL; + FORM_BROWSER_FORM *Form; + + Link = GetFirstNode (&FormSet->FormListHead); + while (!IsNull (&FormSet->FormListHead, Link)) { + Form = FORM_BROWSER_FORM_FROM_LINK (Link); - FreePool (ConfigRespOld); - ConfigRespOld = NULL; + Form->NvUpdateRequired = SetValue; - if (RetVal) { - break; - } + Link = GetNextNode (&FormSet->FormListHead, Link); } - - return RetVal; } - /** Find menu which will show next time. @@ -1852,79 +981,98 @@ IsStorageDataChangedForFormSet ( about the Selection, form and formset to be displayed. On output, Selection return the screen item that is selected by user. - @param SettingLevel Input Settting level, if it is FormLevel, just exit current form. - else, we need to exit current formset. + @param Repaint Whether need to repaint the menu. + @param NewLine Whether need to show at new line. - @retval TRUE Exit current form. - @retval FALSE User press ESC and keep in current form. + @retval TRUE Need return. + @retval FALSE No need to return. **/ BOOLEAN FindNextMenu ( - IN OUT UI_MENU_SELECTION *Selection, - IN BROWSER_SETTING_SCOPE SettingLevel + IN OUT UI_MENU_SELECTION *Selection, + IN BOOLEAN *Repaint, + IN BOOLEAN *NewLine ) { - FORM_ENTRY_INFO *CurrentMenu; - FORM_ENTRY_INFO *ParentMenu; - BROWSER_SETTING_SCOPE Scope; + UI_MENU_LIST *CurrentMenu; + CHAR16 YesResponse; + CHAR16 NoResponse; + EFI_INPUT_KEY Key; + BROWSER_SETTING_SCOPE Scope; CurrentMenu = Selection->CurrentMenu; - ParentMenu = NULL; - Scope = FormSetLevel; - if (CurrentMenu != NULL && (ParentMenu = UiFindParentMenu(CurrentMenu)) != NULL) { + if (CurrentMenu != NULL && CurrentMenu->Parent != NULL) { // // we have a parent, so go to the parent menu // - if (CompareGuid (&CurrentMenu->FormSetGuid, &ParentMenu->FormSetGuid)) { - if (SettingLevel == FormSetLevel) { + if (CompareGuid (&CurrentMenu->FormSetGuid, &CurrentMenu->Parent->FormSetGuid)) { + // + // The parent menu and current menu are in the same formset + // + Selection->Action = UI_ACTION_REFRESH_FORM; + Scope = FormLevel; + } else { + Selection->Action = UI_ACTION_REFRESH_FORMSET; + CopyMem (&Selection->FormSetGuid, &CurrentMenu->Parent->FormSetGuid, sizeof (EFI_GUID)); + Selection->Handle = CurrentMenu->Parent->HiiHandle; + Scope = FormSetLevel; + } + + // + // Form Level Check whether the data is changed. + // + if ((gBrowserSettingScope == FormLevel && Selection->Form->NvUpdateRequired) || + (gBrowserSettingScope == FormSetLevel && IsNvUpdateRequired(Selection->FormSet) && Scope == FormSetLevel)) { + gST->ConIn->ReadKeyStroke (gST->ConIn, &Key); + + YesResponse = gYesResponse[0]; + NoResponse = gNoResponse[0]; + + // + // If NV flag is up, prompt user + // + do { + CreateDialog (4, TRUE, 0, NULL, &Key, gEmptyString, gSaveChanges, gAreYouSure, gEmptyString); + } while + ( + (Key.ScanCode != SCAN_ESC) && + ((Key.UnicodeChar | UPPER_LOWER_CASE_OFFSET) != (NoResponse | UPPER_LOWER_CASE_OFFSET)) && + ((Key.UnicodeChar | UPPER_LOWER_CASE_OFFSET) != (YesResponse | UPPER_LOWER_CASE_OFFSET)) + ); + + if (Key.ScanCode == SCAN_ESC) { // - // Find a menu which has different formset guid with current. + // User hits the ESC key, Ingore. // - while (CompareGuid (&CurrentMenu->FormSetGuid, &ParentMenu->FormSetGuid)) { - CurrentMenu = ParentMenu; - if ((ParentMenu = UiFindParentMenu(CurrentMenu)) == NULL) { - break; - } + if (Repaint != NULL) { + *Repaint = TRUE; } - - if (ParentMenu != NULL) { - Scope = FormSetLevel; + if (NewLine != NULL) { + *NewLine = TRUE; } + + Selection->Action = UI_ACTION_NONE; + return FALSE; + } + + if ((Key.UnicodeChar | UPPER_LOWER_CASE_OFFSET) == (YesResponse | UPPER_LOWER_CASE_OFFSET)) { + // + // If the user hits the YesResponse key + // + SubmitForm (Selection->FormSet, Selection->Form, Scope); } else { - Scope = FormLevel; + // + // If the user hits the NoResponse key + // + DiscardForm (Selection->FormSet, Selection->Form, Scope); } - } else { - Scope = FormSetLevel; - } - } - - // - // Form Level Check whether the data is changed. - // - if ((gBrowserSettingScope == FormLevel && IsNvUpdateRequiredForForm (Selection->Form)) || - (gBrowserSettingScope == FormSetLevel && IsNvUpdateRequiredForFormSet(Selection->FormSet) && Scope == FormSetLevel)) { - if (!ProcessChangedData(Selection, Scope)) { - return FALSE; - } - } - - if (ParentMenu != NULL) { - // - // ParentMenu is found. Then, go to it. - // - if (Scope == FormLevel) { - Selection->Action = UI_ACTION_REFRESH_FORM; - } else { - Selection->Action = UI_ACTION_REFRESH_FORMSET; - CopyMem (&Selection->FormSetGuid, &ParentMenu->FormSetGuid, sizeof (EFI_GUID)); - Selection->Handle = ParentMenu->HiiHandle; } Selection->Statement = NULL; - Selection->FormId = ParentMenu->FormId; - Selection->QuestionId = ParentMenu->QuestionId; + Selection->FormId = CurrentMenu->Parent->FormId; + Selection->QuestionId = CurrentMenu->Parent->QuestionId; // // Clear highlight record for this menu @@ -1933,11 +1081,70 @@ FindNextMenu ( return FALSE; } + if ((gClassOfVfr & FORMSET_CLASS_FRONT_PAGE) == FORMSET_CLASS_FRONT_PAGE) { + // + // We never exit FrontPage, so skip the ESC + // + Selection->Action = UI_ACTION_NONE; + return FALSE; + } + // - // Current in root page, exit the SendForm + // We are going to leave current FormSet, so check uncommited data in this FormSet // - Selection->Action = UI_ACTION_EXIT; + if (gBrowserSettingScope != SystemLevel && IsNvUpdateRequired(Selection->FormSet)) { + gST->ConIn->ReadKeyStroke (gST->ConIn, &Key); + + YesResponse = gYesResponse[0]; + NoResponse = gNoResponse[0]; + + // + // If NV flag is up, prompt user + // + do { + CreateDialog (4, TRUE, 0, NULL, &Key, gEmptyString, gSaveChanges, gAreYouSure, gEmptyString); + } while + ( + (Key.ScanCode != SCAN_ESC) && + ((Key.UnicodeChar | UPPER_LOWER_CASE_OFFSET) != (NoResponse | UPPER_LOWER_CASE_OFFSET)) && + ((Key.UnicodeChar | UPPER_LOWER_CASE_OFFSET) != (YesResponse | UPPER_LOWER_CASE_OFFSET)) + ); + + if (Key.ScanCode == SCAN_ESC) { + // + // User hits the ESC key + // + if (Repaint != NULL) { + *Repaint = TRUE; + } + + if (NewLine != NULL) { + *NewLine = TRUE; + } + + Selection->Action = UI_ACTION_NONE; + return FALSE; + } + if ((Key.UnicodeChar | UPPER_LOWER_CASE_OFFSET) == (YesResponse | UPPER_LOWER_CASE_OFFSET)) { + // + // If the user hits the YesResponse key + // + SubmitForm (Selection->FormSet, Selection->Form, FormSetLevel); + } else { + // + // If the user hits the NoResponse key + // + DiscardForm (Selection->FormSet, Selection->Form, FormSetLevel); + } + } + + Selection->Statement = NULL; + if (CurrentMenu != NULL) { + CurrentMenu->QuestionId = 0; + } + + Selection->Action = UI_ACTION_EXIT; return TRUE; } @@ -2039,17 +1246,17 @@ ProcessCallBackFunction ( case EFI_BROWSER_ACTION_REQUEST_RESET: DiscardFormIsRequired = TRUE; gResetRequired = TRUE; - NeedExit = TRUE; + Selection->Action = UI_ACTION_EXIT; break; case EFI_BROWSER_ACTION_REQUEST_SUBMIT: SubmitFormIsRequired = TRUE; - NeedExit = TRUE; + Selection->Action = UI_ACTION_EXIT; break; case EFI_BROWSER_ACTION_REQUEST_EXIT: DiscardFormIsRequired = TRUE; - NeedExit = TRUE; + Selection->Action = UI_ACTION_EXIT; break; case EFI_BROWSER_ACTION_REQUEST_FORM_SUBMIT_EXIT: @@ -2060,7 +1267,7 @@ ProcessCallBackFunction ( case EFI_BROWSER_ACTION_REQUEST_FORM_DISCARD_EXIT: DiscardFormIsRequired = TRUE; - SettingLevel = FormLevel; + SettingLevel = FormLevel; NeedExit = TRUE; break; @@ -2113,7 +1320,7 @@ ProcessCallBackFunction ( } if (NeedExit) { - FindNextMenu (Selection, SettingLevel); + FindNextMenu (Selection, NULL, NULL); } return Status; @@ -2193,7 +1400,9 @@ SetupBrowser ( EFI_HANDLE NotifyHandle; FORM_BROWSER_STATEMENT *Statement; EFI_HII_CONFIG_ACCESS_PROTOCOL *ConfigAccess; + EFI_INPUT_KEY Key; + gMenuRefreshHead = NULL; ConfigAccess = Selection->FormSet->ConfigAccess; // @@ -2214,17 +1423,21 @@ SetupBrowser ( // // Initialize current settings of Questions in this FormSet // - InitializeCurrentSetting (Selection->FormSet); - - // - // Initilize Action field. - // - Selection->Action = UI_ACTION_REFRESH_FORM; + Status = InitializeCurrentSetting (Selection->FormSet); + if (EFI_ERROR (Status)) { + goto Done; + } // - // Clean the mCurFakeQestId value is formset refreshed. + // Update gOldFormSet on maintain back up FormSet list. + // And, make gOldFormSet point to current FormSet. // - mCurFakeQestId = 0; + if (gOldFormSet != NULL) { + RemoveEntryList (&gOldFormSet->Link); + DestroyFormSet (gOldFormSet); + } + gOldFormSet = Selection->FormSet; + InsertTailList (&gBrowserFormSetList, &gOldFormSet->Link); do { // @@ -2267,7 +1480,10 @@ SetupBrowser ( // // Form is suppressed. // - gBrowserStatus = BROWSER_FORM_SUPPRESS; + do { + CreateDialog (4, TRUE, 0, NULL, &Key, gEmptyString, gFormSuppress, gPressEnter, gEmptyString); + } while (Key.UnicodeChar != CHAR_CARRIAGE_RETURN); + Status = EFI_NOT_FOUND; goto Done; } @@ -2282,6 +1498,7 @@ SetupBrowser ( ((Selection->Handle != mCurrentHiiHandle) || (!CompareGuid (&Selection->FormSetGuid, &mCurrentFormSetGuid)) || (Selection->FormId != mCurrentFormId))) { + // // Keep current form information // @@ -2294,6 +1511,12 @@ SetupBrowser ( goto Done; } + // + // EXIT requests to close form. + // + if (Selection->Action == UI_ACTION_EXIT) { + goto Done; + } // // IFR is updated during callback of open form, force to reparse the IFR binary // @@ -2312,6 +1535,12 @@ SetupBrowser ( goto Done; } + // + // EXIT requests to close form. + // + if (Selection->Action == UI_ACTION_EXIT) { + goto Done; + } // // IFR is updated during callback of read value, force to reparse the IFR binary // @@ -2321,10 +1550,15 @@ SetupBrowser ( break; } + // + // Displays the Header and Footer borders + // + DisplayPageFrame (Selection); + // // Display form // - Status = DisplayForm (); + Status = DisplayForm (Selection); if (EFI_ERROR (Status)) { goto Done; } @@ -2334,16 +1568,20 @@ SetupBrowser ( // Statement = Selection->Statement; if (Statement != NULL) { + if ((Statement->QuestionFlags & EFI_IFR_FLAG_RESET_REQUIRED) == EFI_IFR_FLAG_RESET_REQUIRED) { + gResetRequired = TRUE; + } + if ((ConfigAccess != NULL) && ((Statement->QuestionFlags & EFI_IFR_FLAG_CALLBACK) == EFI_IFR_FLAG_CALLBACK) && (Statement->Operand != EFI_IFR_PASSWORD_OP)) { - Status = ProcessCallBackFunction(Selection, Statement, EFI_BROWSER_ACTION_CHANGING, FALSE); - if (Statement->Operand == EFI_IFR_REF_OP) { + Status = ProcessCallBackFunction(Selection, Statement, EFI_BROWSER_ACTION_CHANGING, FALSE); + if (Statement->Operand == EFI_IFR_REF_OP && Selection->Action != UI_ACTION_EXIT) { // // Process dynamic update ref opcode. // if (!EFI_ERROR (Status)) { - Status = ProcessGotoOpCode(Statement, Selection); + Status = ProcessGotoOpCode(Statement, Selection, NULL, NULL); } // @@ -2364,27 +1602,6 @@ SetupBrowser ( } } - // - // Check whether Exit flag is TRUE. - // - if (gExitRequired) { - switch (gBrowserSettingScope) { - case SystemLevel: - Selection->Action = UI_ACTION_EXIT; - break; - - case FormSetLevel: - case FormLevel: - FindNextMenu (Selection, gBrowserSettingScope); - break; - - default: - break; - } - - gExitRequired = FALSE; - } - // // Before exit the form, invoke ConfigAccess.Callback() with EFI_BROWSER_ACTION_FORM_CLOSE // for each question with callback flag. diff --git a/MdeModulePkg/Universal/SetupBrowserDxe/Print.c b/MdeModulePkg/Universal/SetupBrowserDxe/Print.c new file mode 100644 index 0000000000..eeadf2494f --- /dev/null +++ b/MdeModulePkg/Universal/SetupBrowserDxe/Print.c @@ -0,0 +1,272 @@ +/** @file +Basic Ascii AvSPrintf() function named VSPrint(). VSPrint() enables very +simple implemenation of SPrint() and Print() to support debug. + +You can not Print more than EFI_DRIVER_LIB_MAX_PRINT_BUFFER characters at a +time. This makes the implementation very simple. + +VSPrint, Print, SPrint format specification has the follwoing form + +%type + +type: + 'S','s' - argument is an Unicode string + 'c' - argument is an ascii character + '%' - Print a % + + +Copyright (c) 2004 - 2012, Intel Corporation. All rights reserved.
+This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include "Setup.h" + +/** + The internal function prints to the EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL + protocol instance. + + @param Column The position of the output string. + @param Row The position of the output string. + @param Out The EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL instance. + @param Fmt The format string. + @param Args The additional argument for the variables in the format string. + + @return Number of Unicode character printed. + +**/ +UINTN +PrintInternal ( + IN UINTN Column, + IN UINTN Row, + IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *Out, + IN CHAR16 *Fmt, + IN VA_LIST Args + ) +{ + CHAR16 *Buffer; + CHAR16 *BackupBuffer; + UINTN Index; + UINTN PreviousIndex; + UINTN Count; + + // + // For now, allocate an arbitrarily long buffer + // + Buffer = AllocateZeroPool (0x10000); + BackupBuffer = AllocateZeroPool (0x10000); + ASSERT (Buffer); + ASSERT (BackupBuffer); + + if (Column != (UINTN) -1) { + Out->SetCursorPosition (Out, Column, Row); + } + + UnicodeVSPrint (Buffer, 0x10000, Fmt, Args); + + Out->Mode->Attribute = Out->Mode->Attribute & 0x7f; + + Out->SetAttribute (Out, Out->Mode->Attribute); + + Index = 0; + PreviousIndex = 0; + Count = 0; + + do { + for (; (Buffer[Index] != NARROW_CHAR) && (Buffer[Index] != WIDE_CHAR) && (Buffer[Index] != 0); Index++) { + BackupBuffer[Index] = Buffer[Index]; + } + + if (Buffer[Index] == 0) { + break; + } + // + // Null-terminate the temporary string + // + BackupBuffer[Index] = 0; + + // + // Print this out, we are about to switch widths + // + Out->OutputString (Out, &BackupBuffer[PreviousIndex]); + Count += StrLen (&BackupBuffer[PreviousIndex]); + + // + // Preserve the current index + 1, since this is where we will start printing from next + // + PreviousIndex = Index + 1; + + // + // We are at a narrow or wide character directive. Set attributes and strip it and print it + // + if (Buffer[Index] == NARROW_CHAR) { + // + // Preserve bits 0 - 6 and zero out the rest + // + Out->Mode->Attribute = Out->Mode->Attribute & 0x7f; + Out->SetAttribute (Out, Out->Mode->Attribute); + } else { + // + // Must be wide, set bit 7 ON + // + Out->Mode->Attribute = Out->Mode->Attribute | EFI_WIDE_ATTRIBUTE; + Out->SetAttribute (Out, Out->Mode->Attribute); + } + + Index++; + + } while (Buffer[Index] != 0); + + // + // We hit the end of the string - print it + // + Out->OutputString (Out, &BackupBuffer[PreviousIndex]); + Count += StrLen (&BackupBuffer[PreviousIndex]); + + FreePool (Buffer); + FreePool (BackupBuffer); + return Count; +} + + +/** + Prints a formatted unicode string to the default console. + + @param Fmt Format string + @param ... Variable argument list for format string. + + @return Length of string printed to the console. + +**/ +UINTN +EFIAPI +ConsolePrint ( + IN CHAR16 *Fmt, + ... + ) +{ + VA_LIST Args; + UINTN LengthOfPrinted; + + VA_START (Args, Fmt); + LengthOfPrinted = PrintInternal ((UINTN) -1, (UINTN) -1, gST->ConOut, Fmt, Args); + VA_END (Args); + return LengthOfPrinted; +} + + +/** + Prints a unicode string to the default console, + using L"%s" format. + + @param String String pointer. + + @return Length of string printed to the console + +**/ +UINTN +PrintString ( + IN CHAR16 *String + ) +{ + return ConsolePrint (L"%s", String); +} + + +/** + Prints a chracter to the default console, + using L"%c" format. + + @param Character Character to print. + + @return Length of string printed to the console. + +**/ +UINTN +PrintChar ( + CHAR16 Character + ) +{ + return ConsolePrint (L"%c", Character); +} + + +/** + Prints a formatted unicode string to the default console, at + the supplied cursor position. + + @param Column The cursor position to print the string at. + @param Row The cursor position to print the string at. + @param Fmt Format string. + @param ... Variable argument list for format string. + + @return Length of string printed to the console + +**/ +UINTN +EFIAPI +PrintAt ( + IN UINTN Column, + IN UINTN Row, + IN CHAR16 *Fmt, + ... + ) +{ + VA_LIST Args; + UINTN LengthOfPrinted; + + VA_START (Args, Fmt); + LengthOfPrinted = PrintInternal (Column, Row, gST->ConOut, Fmt, Args); + VA_END (Args); + return LengthOfPrinted; +} + + +/** + Prints a unicode string to the default console, at + the supplied cursor position, using L"%s" format. + + @param Column The cursor position to print the string at. + @param Row The cursor position to print the string at + @param String String pointer. + + @return Length of string printed to the console + +**/ +UINTN +PrintStringAt ( + IN UINTN Column, + IN UINTN Row, + IN CHAR16 *String + ) +{ + return PrintAt (Column, Row, L"%s", String); +} + + +/** + Prints a chracter to the default console, at + the supplied cursor position, using L"%c" format. + + @param Column The cursor position to print the string at. + @param Row The cursor position to print the string at. + @param Character Character to print. + + @return Length of string printed to the console. + +**/ +UINTN +PrintCharAt ( + IN UINTN Column, + IN UINTN Row, + CHAR16 Character + ) +{ + return PrintAt (Column, Row, L"%c", Character); +} diff --git a/MdeModulePkg/Universal/SetupBrowserDxe/ProcessOptions.c b/MdeModulePkg/Universal/SetupBrowserDxe/ProcessOptions.c new file mode 100644 index 0000000000..fecb98e8bf --- /dev/null +++ b/MdeModulePkg/Universal/SetupBrowserDxe/ProcessOptions.c @@ -0,0 +1,1075 @@ +/** @file +Implementation for handling the User Interface option processing. + + +Copyright (c) 2004 - 2012, Intel Corporation. All rights reserved.
+This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include "Setup.h" + + +/** + Process Question Config. + + @param Selection The UI menu selection. + @param Question The Question to be peocessed. + + @retval EFI_SUCCESS Question Config process success. + @retval Other Question Config process fail. + +**/ +EFI_STATUS +ProcessQuestionConfig ( + IN UI_MENU_SELECTION *Selection, + IN FORM_BROWSER_STATEMENT *Question + ) +{ + EFI_STATUS Status; + CHAR16 *ConfigResp; + CHAR16 *Progress; + EFI_HII_CONFIG_ACCESS_PROTOCOL *ConfigAccess; + + if (Question->QuestionConfig == 0) { + return EFI_SUCCESS; + } + + // + // Get + // + ConfigResp = GetToken (Question->QuestionConfig, Selection->FormSet->HiiHandle); + if (ConfigResp == NULL) { + return EFI_NOT_FOUND; + } + + // + // Send config to Configuration Driver + // + ConfigAccess = Selection->FormSet->ConfigAccess; + if (ConfigAccess == NULL) { + return EFI_UNSUPPORTED; + } + Status = ConfigAccess->RouteConfig ( + ConfigAccess, + ConfigResp, + &Progress + ); + + return Status; +} + + +/** + Search an Option of a Question by its value. + + @param Question The Question + @param OptionValue Value for Option to be searched. + + @retval Pointer Pointer to the found Option. + @retval NULL Option not found. + +**/ +QUESTION_OPTION * +ValueToOption ( + IN FORM_BROWSER_STATEMENT *Question, + IN EFI_HII_VALUE *OptionValue + ) +{ + LIST_ENTRY *Link; + QUESTION_OPTION *Option; + INTN Result; + + Link = GetFirstNode (&Question->OptionListHead); + while (!IsNull (&Question->OptionListHead, Link)) { + Option = QUESTION_OPTION_FROM_LINK (Link); + + if ((CompareHiiValue (&Option->Value, OptionValue, &Result, NULL) == EFI_SUCCESS) && (Result == 0)) { + // + // Check the suppressif condition, only a valid option can be return. + // + if ((Option->SuppressExpression == NULL) || + ((EvaluateExpressionList(Option->SuppressExpression, FALSE, NULL, NULL) == ExpressFalse))) { + return Option; + } + } + + Link = GetNextNode (&Question->OptionListHead, Link); + } + + return NULL; +} + + +/** + Return data element in an Array by its Index. + + @param Array The data array. + @param Type Type of the data in this array. + @param Index Zero based index for data in this array. + + @retval Value The data to be returned + +**/ +UINT64 +GetArrayData ( + IN VOID *Array, + IN UINT8 Type, + IN UINTN Index + ) +{ + UINT64 Data; + + ASSERT (Array != NULL); + + Data = 0; + switch (Type) { + case EFI_IFR_TYPE_NUM_SIZE_8: + Data = (UINT64) *(((UINT8 *) Array) + Index); + break; + + case EFI_IFR_TYPE_NUM_SIZE_16: + Data = (UINT64) *(((UINT16 *) Array) + Index); + break; + + case EFI_IFR_TYPE_NUM_SIZE_32: + Data = (UINT64) *(((UINT32 *) Array) + Index); + break; + + case EFI_IFR_TYPE_NUM_SIZE_64: + Data = (UINT64) *(((UINT64 *) Array) + Index); + break; + + default: + break; + } + + return Data; +} + + +/** + Set value of a data element in an Array by its Index. + + @param Array The data array. + @param Type Type of the data in this array. + @param Index Zero based index for data in this array. + @param Value The value to be set. + +**/ +VOID +SetArrayData ( + IN VOID *Array, + IN UINT8 Type, + IN UINTN Index, + IN UINT64 Value + ) +{ + + ASSERT (Array != NULL); + + switch (Type) { + case EFI_IFR_TYPE_NUM_SIZE_8: + *(((UINT8 *) Array) + Index) = (UINT8) Value; + break; + + case EFI_IFR_TYPE_NUM_SIZE_16: + *(((UINT16 *) Array) + Index) = (UINT16) Value; + break; + + case EFI_IFR_TYPE_NUM_SIZE_32: + *(((UINT32 *) Array) + Index) = (UINT32) Value; + break; + + case EFI_IFR_TYPE_NUM_SIZE_64: + *(((UINT64 *) Array) + Index) = (UINT64) Value; + break; + + default: + break; + } +} + +/** + Check whether this value already in the array, if yes, return the index. + + @param Array The data array. + @param Type Type of the data in this array. + @param Value The value to be find. + @param Index The index in the array which has same value with Value. + + @retval TRUE Found the value in the array. + @retval FALSE Not found the value. + +**/ +BOOLEAN +FindArrayData ( + IN VOID *Array, + IN UINT8 Type, + IN UINT64 Value, + OUT UINTN *Index OPTIONAL + ) +{ + UINTN Count; + UINT64 TmpValue; + + ASSERT (Array != NULL); + + Count = 0; + TmpValue = 0; + + while ((TmpValue = GetArrayData (Array, Type, Count)) != 0) { + if (Value == TmpValue) { + if (Index != NULL) { + *Index = Count; + } + return TRUE; + } + + Count ++; + } + + return FALSE; +} + +/** + Print Question Value according to it's storage width and display attributes. + + @param Question The Question to be printed. + @param FormattedNumber Buffer for output string. + @param BufferSize The FormattedNumber buffer size in bytes. + + @retval EFI_SUCCESS Print success. + @retval EFI_BUFFER_TOO_SMALL Buffer size is not enough for formatted number. + +**/ +EFI_STATUS +PrintFormattedNumber ( + IN FORM_BROWSER_STATEMENT *Question, + IN OUT CHAR16 *FormattedNumber, + IN UINTN BufferSize + ) +{ + INT64 Value; + CHAR16 *Format; + EFI_HII_VALUE *QuestionValue; + + if (BufferSize < (21 * sizeof (CHAR16))) { + return EFI_BUFFER_TOO_SMALL; + } + + QuestionValue = &Question->HiiValue; + + Value = (INT64) QuestionValue->Value.u64; + switch (Question->Flags & EFI_IFR_DISPLAY) { + case EFI_IFR_DISPLAY_INT_DEC: + switch (QuestionValue->Type) { + case EFI_IFR_NUMERIC_SIZE_1: + Value = (INT64) ((INT8) QuestionValue->Value.u8); + break; + + case EFI_IFR_NUMERIC_SIZE_2: + Value = (INT64) ((INT16) QuestionValue->Value.u16); + break; + + case EFI_IFR_NUMERIC_SIZE_4: + Value = (INT64) ((INT32) QuestionValue->Value.u32); + break; + + case EFI_IFR_NUMERIC_SIZE_8: + default: + break; + } + + if (Value < 0) { + Value = -Value; + Format = L"-%ld"; + } else { + Format = L"%ld"; + } + break; + + case EFI_IFR_DISPLAY_UINT_DEC: + Format = L"%ld"; + break; + + case EFI_IFR_DISPLAY_UINT_HEX: + Format = L"%lx"; + break; + + default: + return EFI_UNSUPPORTED; + break; + } + + UnicodeSPrint (FormattedNumber, BufferSize, Format, Value); + + return EFI_SUCCESS; +} + + +/** + Password may be stored as encrypted by Configuration Driver. When change a + password, user will be challenged with old password. To validate user input old + password, we will send the clear text to Configuration Driver via Callback(). + Configuration driver is responsible to check the passed in password and return + the validation result. If validation pass, state machine in password Callback() + will transit from BROWSER_STATE_VALIDATE_PASSWORD to BROWSER_STATE_SET_PASSWORD. + After user type in new password twice, Callback() will be invoked to send the + new password to Configuration Driver. + + @param Selection Pointer to UI_MENU_SELECTION. + @param MenuOption The MenuOption for this password Question. + @param String The clear text of password. + + @retval EFI_NOT_AVAILABLE_YET Callback() request to terminate password input. + @return In state of BROWSER_STATE_VALIDATE_PASSWORD: + @retval EFI_SUCCESS Password correct, Browser will prompt for new + password. + @retval EFI_NOT_READY Password incorrect, Browser will show error + message. + @retval Other Browser will do nothing. + @return In state of BROWSER_STATE_SET_PASSWORD: + @retval EFI_SUCCESS Set password success. + @retval Other Set password failed. + +**/ +EFI_STATUS +PasswordCallback ( + IN UI_MENU_SELECTION *Selection, + IN UI_MENU_OPTION *MenuOption, + IN CHAR16 *String + ) +{ + EFI_STATUS Status; + EFI_HII_CONFIG_ACCESS_PROTOCOL *ConfigAccess; + EFI_BROWSER_ACTION_REQUEST ActionRequest; + EFI_IFR_TYPE_VALUE IfrTypeValue; + + ConfigAccess = Selection->FormSet->ConfigAccess; + if (ConfigAccess == NULL) { + return EFI_UNSUPPORTED; + } + + // + // Prepare password string in HII database + // + if (String != NULL) { + IfrTypeValue.string = NewString (String, Selection->FormSet->HiiHandle); + } else { + IfrTypeValue.string = 0; + } + + // + // Send password to Configuration Driver for validation + // + Status = ConfigAccess->Callback ( + ConfigAccess, + EFI_BROWSER_ACTION_CHANGING, + MenuOption->ThisTag->QuestionId, + MenuOption->ThisTag->HiiValue.Type, + &IfrTypeValue, + &ActionRequest + ); + + // + // Remove password string from HII database + // + if (String != NULL) { + DeleteString (IfrTypeValue.string, Selection->FormSet->HiiHandle); + } + + return Status; +} + + +/** + Display error message for invalid password. + +**/ +VOID +PasswordInvalid ( + VOID + ) +{ + EFI_INPUT_KEY Key; + + // + // Invalid password, prompt error message + // + do { + CreateDialog (4, TRUE, 0, NULL, &Key, gEmptyString, gPassowordInvalid, gPressEnter, gEmptyString); + } while (Key.UnicodeChar != CHAR_CARRIAGE_RETURN); +} + + +/** + Process a Question's Option (whether selected or un-selected). + + @param Selection Pointer to UI_MENU_SELECTION. + @param MenuOption The MenuOption for this Question. + @param Selected TRUE: if Question is selected. + @param OptionString Pointer of the Option String to be displayed. + + @retval EFI_SUCCESS Question Option process success. + @retval Other Question Option process fail. + +**/ +EFI_STATUS +ProcessOptions ( + IN UI_MENU_SELECTION *Selection, + IN UI_MENU_OPTION *MenuOption, + IN BOOLEAN Selected, + OUT CHAR16 **OptionString + ) +{ + EFI_STATUS Status; + CHAR16 *StringPtr; + CHAR16 *TempString; + UINTN Index; + FORM_BROWSER_STATEMENT *Question; + CHAR16 FormattedNumber[21]; + UINT16 Number; + CHAR16 Character[2]; + EFI_INPUT_KEY Key; + UINTN BufferSize; + QUESTION_OPTION *OneOfOption; + LIST_ENTRY *Link; + EFI_HII_VALUE HiiValue; + EFI_HII_VALUE *QuestionValue; + UINT16 Maximum; + QUESTION_OPTION *Option; + UINTN Index2; + UINT8 *ValueArray; + UINT8 ValueType; + EFI_STRING_ID StringId; + + Status = EFI_SUCCESS; + + StringPtr = NULL; + Character[1] = L'\0'; + *OptionString = NULL; + StringId = 0; + + ZeroMem (FormattedNumber, 21 * sizeof (CHAR16)); + BufferSize = (gOptionBlockWidth + 1) * 2 * gScreenDimensions.BottomRow; + + Question = MenuOption->ThisTag; + QuestionValue = &Question->HiiValue; + Maximum = (UINT16) Question->Maximum; + + ValueArray = Question->BufferValue; + ValueType = Question->ValueType; + + switch (Question->Operand) { + case EFI_IFR_ORDERED_LIST_OP: + // + // Check whether there are Options of this OrderedList + // + if (IsListEmpty (&Question->OptionListHead)) { + break; + } + // + // Initialize Option value array + // + if (GetArrayData (ValueArray, ValueType, 0) == 0) { + GetQuestionDefault (Selection->FormSet, Selection->Form, Question, 0); + } + + if (Selected) { + // + // Go ask for input + // + Status = GetSelectionInputPopUp (Selection, MenuOption); + } else { + // + // We now know how many strings we will have, so we can allocate the + // space required for the array or strings. + // + *OptionString = AllocateZeroPool (Question->MaxContainers * BufferSize); + ASSERT (*OptionString); + + HiiValue.Type = ValueType; + HiiValue.Value.u64 = 0; + for (Index = 0; Index < Question->MaxContainers; Index++) { + HiiValue.Value.u64 = GetArrayData (ValueArray, ValueType, Index); + if (HiiValue.Value.u64 == 0) { + // + // Values for the options in ordered lists should never be a 0 + // + break; + } + + OneOfOption = ValueToOption (Question, &HiiValue); + if (OneOfOption == NULL) { + // + // Show error message + // + do { + CreateDialog (4, TRUE, 0, NULL, &Key, gEmptyString, gOptionMismatch, gPressEnter, gEmptyString); + } while (Key.UnicodeChar != CHAR_CARRIAGE_RETURN); + + // + // The initial value of the orderedlist is invalid, force to be valid value + // + Link = GetFirstNode (&Question->OptionListHead); + Index2 = 0; + while (!IsNull (&Question->OptionListHead, Link) && Index2 < Question->MaxContainers) { + Option = QUESTION_OPTION_FROM_LINK (Link); + Link = GetNextNode (&Question->OptionListHead, Link); + if ((Option->SuppressExpression != NULL) && + ((EvaluateExpressionList(Option->SuppressExpression, FALSE, NULL, NULL) == ExpressSuppress))) { + continue; + } + SetArrayData (ValueArray, ValueType, Index2, Option->Value.Value.u64); + Index2++; + } + SetArrayData (ValueArray, ValueType, Index2, 0); + + Status = SetQuestionValue (Selection->FormSet, Selection->Form, Question, GetSetValueWithEditBuffer); + UpdateStatusBar (Selection, NV_UPDATE_REQUIRED, Question->QuestionFlags, TRUE); + + FreePool (*OptionString); + *OptionString = NULL; + return EFI_NOT_FOUND; + } + + Character[0] = LEFT_ONEOF_DELIMITER; + NewStrCat (OptionString[0], Character); + StringPtr = GetToken (OneOfOption->Text, Selection->Handle); + ASSERT (StringPtr != NULL); + NewStrCat (OptionString[0], StringPtr); + Character[0] = RIGHT_ONEOF_DELIMITER; + NewStrCat (OptionString[0], Character); + Character[0] = CHAR_CARRIAGE_RETURN; + NewStrCat (OptionString[0], Character); + FreePool (StringPtr); + } + + // + // Search the other options, try to find the one not in the container. + // + Link = GetFirstNode (&Question->OptionListHead); + while (!IsNull (&Question->OptionListHead, Link)) { + OneOfOption = QUESTION_OPTION_FROM_LINK (Link); + Link = GetNextNode (&Question->OptionListHead, Link); + if ((OneOfOption->SuppressExpression != NULL) && + ((EvaluateExpressionList(OneOfOption->SuppressExpression, FALSE, NULL, NULL) == ExpressSuppress))) { + continue; + } + + if (FindArrayData (ValueArray, ValueType, OneOfOption->Value.Value.u64, NULL)) { + continue; + } + + SetArrayData (ValueArray, ValueType, Index++, OneOfOption->Value.Value.u64); + + Character[0] = LEFT_ONEOF_DELIMITER; + NewStrCat (OptionString[0], Character); + StringPtr = GetToken (OneOfOption->Text, Selection->Handle); + ASSERT (StringPtr != NULL); + NewStrCat (OptionString[0], StringPtr); + Character[0] = RIGHT_ONEOF_DELIMITER; + NewStrCat (OptionString[0], Character); + Character[0] = CHAR_CARRIAGE_RETURN; + NewStrCat (OptionString[0], Character); + FreePool (StringPtr); + } + } + break; + + case EFI_IFR_ONE_OF_OP: + // + // Check whether there are Options of this OneOf + // + if (IsListEmpty (&Question->OptionListHead)) { + break; + } + if (Selected) { + // + // Go ask for input + // + Status = GetSelectionInputPopUp (Selection, MenuOption); + } else { + *OptionString = AllocateZeroPool (BufferSize); + ASSERT (*OptionString); + + OneOfOption = ValueToOption (Question, QuestionValue); + if (OneOfOption == NULL) { + // + // Show error message + // + do { + CreateDialog (4, TRUE, 0, NULL, &Key, gEmptyString, gOptionMismatch, gPressEnter, gEmptyString); + } while (Key.UnicodeChar != CHAR_CARRIAGE_RETURN); + + // + // Force the Question value to be valid + // + Link = GetFirstNode (&Question->OptionListHead); + while (!IsNull (&Question->OptionListHead, Link)) { + Option = QUESTION_OPTION_FROM_LINK (Link); + + if ((Option->SuppressExpression == NULL) || + (EvaluateExpressionList(Option->SuppressExpression, FALSE, NULL, NULL) == ExpressFalse)) { + CopyMem (QuestionValue, &Option->Value, sizeof (EFI_HII_VALUE)); + SetQuestionValue (Selection->FormSet, Selection->Form, Question, GetSetValueWithEditBuffer); + UpdateStatusBar (Selection, NV_UPDATE_REQUIRED, Question->QuestionFlags, TRUE); + break; + } + + Link = GetNextNode (&Question->OptionListHead, Link); + } + + FreePool (*OptionString); + *OptionString = NULL; + return EFI_NOT_FOUND; + } + + Character[0] = LEFT_ONEOF_DELIMITER; + NewStrCat (OptionString[0], Character); + StringPtr = GetToken (OneOfOption->Text, Selection->Handle); + ASSERT (StringPtr != NULL); + NewStrCat (OptionString[0], StringPtr); + Character[0] = RIGHT_ONEOF_DELIMITER; + NewStrCat (OptionString[0], Character); + + FreePool (StringPtr); + } + break; + + case EFI_IFR_CHECKBOX_OP: + *OptionString = AllocateZeroPool (BufferSize); + ASSERT (*OptionString); + + *OptionString[0] = LEFT_CHECKBOX_DELIMITER; + + if (Selected) { + // + // Since this is a BOOLEAN operation, flip it upon selection + // + QuestionValue->Value.b = (BOOLEAN) (QuestionValue->Value.b ? FALSE : TRUE); + + // + // Perform inconsistent check + // + Status = ValidateQuestion (Selection->FormSet, Selection->Form, Question, EFI_HII_EXPRESSION_INCONSISTENT_IF); + if (EFI_ERROR (Status)) { + // + // Inconsistent check fail, restore Question Value + // + QuestionValue->Value.b = (BOOLEAN) (QuestionValue->Value.b ? FALSE : TRUE); + FreePool (*OptionString); + *OptionString = NULL; + return Status; + } + + // + // Save Question value + // + Status = SetQuestionValue (Selection->FormSet, Selection->Form, Question, GetSetValueWithEditBuffer); + UpdateStatusBar (Selection, NV_UPDATE_REQUIRED, Question->QuestionFlags, TRUE); + } + + if (QuestionValue->Value.b) { + *(OptionString[0] + 1) = CHECK_ON; + } else { + *(OptionString[0] + 1) = CHECK_OFF; + } + *(OptionString[0] + 2) = RIGHT_CHECKBOX_DELIMITER; + break; + + case EFI_IFR_NUMERIC_OP: + if (Selected) { + // + // Go ask for input + // + Status = GetNumericInput (Selection, MenuOption); + } else { + *OptionString = AllocateZeroPool (BufferSize); + ASSERT (*OptionString); + + *OptionString[0] = LEFT_NUMERIC_DELIMITER; + + // + // Formatted print + // + PrintFormattedNumber (Question, FormattedNumber, 21 * sizeof (CHAR16)); + Number = (UINT16) GetStringWidth (FormattedNumber); + CopyMem (OptionString[0] + 1, FormattedNumber, Number); + + *(OptionString[0] + Number / 2) = RIGHT_NUMERIC_DELIMITER; + } + break; + + case EFI_IFR_DATE_OP: + if (Selected) { + // + // This is similar to numerics + // + Status = GetNumericInput (Selection, MenuOption); + } else { + *OptionString = AllocateZeroPool (BufferSize); + ASSERT (*OptionString); + + switch (MenuOption->Sequence) { + case 0: + *OptionString[0] = LEFT_NUMERIC_DELIMITER; + UnicodeSPrint (OptionString[0] + 1, 21 * sizeof (CHAR16), L"%02d", QuestionValue->Value.date.Month); + *(OptionString[0] + 3) = DATE_SEPARATOR; + break; + + case 1: + SetUnicodeMem (OptionString[0], 4, L' '); + UnicodeSPrint (OptionString[0] + 4, 21 * sizeof (CHAR16), L"%02d", QuestionValue->Value.date.Day); + *(OptionString[0] + 6) = DATE_SEPARATOR; + break; + + case 2: + SetUnicodeMem (OptionString[0], 7, L' '); + UnicodeSPrint (OptionString[0] + 7, 21 * sizeof (CHAR16), L"%04d", QuestionValue->Value.date.Year); + *(OptionString[0] + 11) = RIGHT_NUMERIC_DELIMITER; + break; + } + } + break; + + case EFI_IFR_TIME_OP: + if (Selected) { + // + // This is similar to numerics + // + Status = GetNumericInput (Selection, MenuOption); + } else { + *OptionString = AllocateZeroPool (BufferSize); + ASSERT (*OptionString); + + switch (MenuOption->Sequence) { + case 0: + *OptionString[0] = LEFT_NUMERIC_DELIMITER; + UnicodeSPrint (OptionString[0] + 1, 21 * sizeof (CHAR16), L"%02d", QuestionValue->Value.time.Hour); + *(OptionString[0] + 3) = TIME_SEPARATOR; + break; + + case 1: + SetUnicodeMem (OptionString[0], 4, L' '); + UnicodeSPrint (OptionString[0] + 4, 21 * sizeof (CHAR16), L"%02d", QuestionValue->Value.time.Minute); + *(OptionString[0] + 6) = TIME_SEPARATOR; + break; + + case 2: + SetUnicodeMem (OptionString[0], 7, L' '); + UnicodeSPrint (OptionString[0] + 7, 21 * sizeof (CHAR16), L"%02d", QuestionValue->Value.time.Second); + *(OptionString[0] + 9) = RIGHT_NUMERIC_DELIMITER; + break; + } + } + break; + + case EFI_IFR_STRING_OP: + if (Selected) { + StringPtr = AllocateZeroPool ((Maximum + 1) * sizeof (CHAR16)); + ASSERT (StringPtr); + CopyMem(StringPtr, Question->BufferValue, Maximum * sizeof (CHAR16)); + + Status = ReadString (MenuOption, gPromptForData, StringPtr); + if (!EFI_ERROR (Status)) { + HiiSetString(Selection->FormSet->HiiHandle, Question->HiiValue.Value.string, StringPtr, NULL); + Status = ValidateQuestion(Selection->FormSet, Selection->Form, Question, EFI_HII_EXPRESSION_INCONSISTENT_IF); + if (EFI_ERROR (Status)) { + HiiSetString(Selection->FormSet->HiiHandle, Question->HiiValue.Value.string, (CHAR16*)Question->BufferValue, NULL); + } else { + CopyMem (Question->BufferValue, StringPtr, Maximum * sizeof (CHAR16)); + SetQuestionValue (Selection->FormSet, Selection->Form, Question, GetSetValueWithEditBuffer); + + UpdateStatusBar (Selection, NV_UPDATE_REQUIRED, Question->QuestionFlags, TRUE); + } + } + + FreePool (StringPtr); + } else { + *OptionString = AllocateZeroPool (BufferSize); + ASSERT (*OptionString); + + if (((CHAR16 *) Question->BufferValue)[0] == 0x0000) { + *(OptionString[0]) = '_'; + } else { + if ((Maximum * sizeof (CHAR16)) < BufferSize) { + BufferSize = Maximum * sizeof (CHAR16); + } + CopyMem (OptionString[0], (CHAR16 *) Question->BufferValue, BufferSize); + } + } + break; + + case EFI_IFR_PASSWORD_OP: + if (Selected) { + StringPtr = AllocateZeroPool ((Maximum + 1) * sizeof (CHAR16)); + ASSERT (StringPtr); + + // + // For interactive passwords, old password is validated by callback + // + if ((Question->QuestionFlags & EFI_IFR_FLAG_CALLBACK) != 0) { + // + // Use a NULL password to test whether old password is required + // + *StringPtr = 0; + Status = PasswordCallback (Selection, MenuOption, StringPtr); + if (Status == EFI_NOT_AVAILABLE_YET || Status == EFI_UNSUPPORTED) { + // + // Callback is not supported, or + // Callback request to terminate password input + // + FreePool (StringPtr); + return EFI_SUCCESS; + } + + if (EFI_ERROR (Status)) { + // + // Old password exist, ask user for the old password + // + Status = ReadString (MenuOption, gPromptForPassword, StringPtr); + if (EFI_ERROR (Status)) { + FreePool (StringPtr); + return Status; + } + + // + // Check user input old password + // + Status = PasswordCallback (Selection, MenuOption, StringPtr); + if (EFI_ERROR (Status)) { + if (Status == EFI_NOT_READY) { + // + // Typed in old password incorrect + // + PasswordInvalid (); + } else { + Status = EFI_SUCCESS; + } + + FreePool (StringPtr); + return Status; + } + } + } else { + // + // For non-interactive password, validate old password in local + // + if (*((CHAR16 *) Question->BufferValue) != 0) { + // + // There is something there! Prompt for password + // + Status = ReadString (MenuOption, gPromptForPassword, StringPtr); + if (EFI_ERROR (Status)) { + FreePool (StringPtr); + return Status; + } + + TempString = AllocateCopyPool ((Maximum + 1) * sizeof (CHAR16), Question->BufferValue); + ASSERT (TempString != NULL); + + TempString[Maximum] = L'\0'; + + if (StrCmp (StringPtr, TempString) != 0) { + // + // Typed in old password incorrect + // + PasswordInvalid (); + + FreePool (StringPtr); + FreePool (TempString); + return Status; + } + + FreePool (TempString); + } + } + + // + // Ask for new password + // + ZeroMem (StringPtr, (Maximum + 1) * sizeof (CHAR16)); + Status = ReadString (MenuOption, gPromptForNewPassword, StringPtr); + if (EFI_ERROR (Status)) { + // + // Reset state machine for interactive password + // + if ((Question->QuestionFlags & EFI_IFR_FLAG_CALLBACK) != 0) { + PasswordCallback (Selection, MenuOption, NULL); + } + + FreePool (StringPtr); + return Status; + } + + // + // Confirm new password + // + TempString = AllocateZeroPool ((Maximum + 1) * sizeof (CHAR16)); + ASSERT (TempString); + Status = ReadString (MenuOption, gConfirmPassword, TempString); + if (EFI_ERROR (Status)) { + // + // Reset state machine for interactive password + // + if ((Question->QuestionFlags & EFI_IFR_FLAG_CALLBACK) != 0) { + PasswordCallback (Selection, MenuOption, NULL); + } + + FreePool (StringPtr); + FreePool (TempString); + return Status; + } + + // + // Compare two typed-in new passwords + // + if (StrCmp (StringPtr, TempString) == 0) { + // + // Prepare the Question->HiiValue.Value.string for ValidateQuestion use. + // + if((Question->QuestionFlags & EFI_IFR_FLAG_CALLBACK) != 0) { + StringId = Question->HiiValue.Value.string; + Question->HiiValue.Value.string = NewString (StringPtr, Selection->FormSet->HiiHandle); + } else { + HiiSetString(Selection->FormSet->HiiHandle, Question->HiiValue.Value.string, StringPtr, NULL); + } + + Status = ValidateQuestion(Selection->FormSet, Selection->Form, Question, EFI_HII_EXPRESSION_INCONSISTENT_IF); + + // + // Researve the Question->HiiValue.Value.string. + // + if((Question->QuestionFlags & EFI_IFR_FLAG_CALLBACK) != 0) { + DeleteString(Question->HiiValue.Value.string, Selection->FormSet->HiiHandle); + Question->HiiValue.Value.string = StringId; + } + + if (EFI_ERROR (Status)) { + // + // Reset state machine for interactive password + // + if ((Question->QuestionFlags & EFI_IFR_FLAG_CALLBACK) != 0) { + PasswordCallback (Selection, MenuOption, NULL); + } else { + // + // Researve the Question->HiiValue.Value.string. + // + HiiSetString(Selection->FormSet->HiiHandle, Question->HiiValue.Value.string, (CHAR16*)Question->BufferValue, NULL); + } + } else { + // + // Two password match, send it to Configuration Driver + // + if ((Question->QuestionFlags & EFI_IFR_FLAG_CALLBACK) != 0) { + PasswordCallback (Selection, MenuOption, StringPtr); + } else { + CopyMem (Question->BufferValue, StringPtr, Maximum * sizeof (CHAR16)); + SetQuestionValue (Selection->FormSet, Selection->Form, Question, GetSetValueWithHiiDriver); + } + } + } else { + // + // Reset state machine for interactive password + // + if ((Question->QuestionFlags & EFI_IFR_FLAG_CALLBACK) != 0) { + PasswordCallback (Selection, MenuOption, NULL); + } + + // + // Two password mismatch, prompt error message + // + do { + CreateDialog (4, TRUE, 0, NULL, &Key, gEmptyString, gConfirmError, gPressEnter, gEmptyString); + } while (Key.UnicodeChar != CHAR_CARRIAGE_RETURN); + } + + FreePool (TempString); + FreePool (StringPtr); + } + break; + + default: + break; + } + + return Status; +} + + +/** + Process the help string: Split StringPtr to several lines of strings stored in + FormattedString and the glyph width of each line cannot exceed gHelpBlockWidth. + + @param StringPtr The entire help string. + @param FormattedString The oupput formatted string. + @param EachLineWidth The max string length of each line in the formatted string. + @param RowCount TRUE: if Question is selected. + +**/ +UINTN +ProcessHelpString ( + IN CHAR16 *StringPtr, + OUT CHAR16 **FormattedString, + OUT UINT16 *EachLineWidth, + IN UINTN RowCount + ) +{ + UINTN Index; + CHAR16 *OutputString; + UINTN TotalRowNum; + UINTN CheckedNum; + UINT16 GlyphWidth; + UINT16 LineWidth; + UINT16 MaxStringLen; + UINT16 StringLen; + + TotalRowNum = 0; + CheckedNum = 0; + GlyphWidth = 1; + Index = 0; + MaxStringLen = 0; + StringLen = 0; + + // + // Set default help string width. + // + LineWidth = (UINT16) (gHelpBlockWidth - 1); + + // + // Get row number of the String. + // + while ((StringLen = GetLineByWidth (StringPtr, LineWidth, &GlyphWidth, &Index, &OutputString)) != 0) { + if (StringLen > MaxStringLen) { + MaxStringLen = StringLen; + } + + TotalRowNum ++; + FreePool (OutputString); + } + *EachLineWidth = MaxStringLen; + + *FormattedString = AllocateZeroPool (TotalRowNum * MaxStringLen * sizeof (CHAR16)); + ASSERT (*FormattedString != NULL); + + // + // Generate formatted help string array. + // + GlyphWidth = 1; + Index = 0; + while((StringLen = GetLineByWidth (StringPtr, LineWidth, &GlyphWidth, &Index, &OutputString)) != 0) { + CopyMem (*FormattedString + CheckedNum * MaxStringLen, OutputString, StringLen * sizeof (CHAR16)); + CheckedNum ++; + FreePool (OutputString); + } + + return TotalRowNum; +} diff --git a/MdeModulePkg/Universal/SetupBrowserDxe/Setup.c b/MdeModulePkg/Universal/SetupBrowserDxe/Setup.c index ba72d1220b..ed904161b6 100644 --- a/MdeModulePkg/Universal/SetupBrowserDxe/Setup.c +++ b/MdeModulePkg/Universal/SetupBrowserDxe/Setup.c @@ -26,281 +26,167 @@ SETUP_DRIVER_PRIVATE_DATA mPrivateData = { RegisterHotKey, RegiserExitHandler, SaveReminder - }, - { - BROWSER_EXTENSION2_VERSION_1, - SetScope, - RegisterHotKey, - RegiserExitHandler, - IsBrowserDataModified, - ExecuteAction, } }; EFI_HII_DATABASE_PROTOCOL *mHiiDatabase; +EFI_HII_STRING_PROTOCOL *mHiiString; EFI_HII_CONFIG_ROUTING_PROTOCOL *mHiiConfigRouting; EFI_DEVICE_PATH_FROM_TEXT_PROTOCOL *mPathFromText; -EDKII_FORM_DISPLAY_ENGINE_PROTOCOL *mFormDisplay; UINTN gBrowserContextCount = 0; LIST_ENTRY gBrowserContextList = INITIALIZE_LIST_HEAD_VARIABLE (gBrowserContextList); LIST_ENTRY gBrowserFormSetList = INITIALIZE_LIST_HEAD_VARIABLE (gBrowserFormSetList); LIST_ENTRY gBrowserHotKeyList = INITIALIZE_LIST_HEAD_VARIABLE (gBrowserHotKeyList); -LIST_ENTRY gBrowserStorageList = INITIALIZE_LIST_HEAD_VARIABLE (gBrowserStorageList); +LIST_ENTRY gBrowserStorageList = INITIALIZE_LIST_HEAD_VARIABLE (gBrowserStorageList); +BANNER_DATA *gBannerData; +EFI_HII_HANDLE gFrontPageHandle; +UINTN gClassOfVfr; +UINTN gFunctionKeySetting; BOOLEAN gResetRequired; -BOOLEAN gExitRequired; +EFI_HII_HANDLE gHiiHandle; +UINT16 gDirection; +EFI_SCREEN_DESCRIPTOR gScreenDimensions; BROWSER_SETTING_SCOPE gBrowserSettingScope = FormSetLevel; BOOLEAN mBrowserScopeFirstSet = TRUE; EXIT_HANDLER ExitHandlerFunction = NULL; +UINTN gFooterHeight; // // Browser Global Strings // +CHAR16 *gSaveFailed; +CHAR16 *gDiscardFailed; +CHAR16 *gDefaultFailed; +CHAR16 *gEnterString; +CHAR16 *gEnterCommitString; +CHAR16 *gEnterEscapeString; +CHAR16 *gEscapeString; +CHAR16 *gMoveHighlight; +CHAR16 *gMakeSelection; +CHAR16 *gDecNumericInput; +CHAR16 *gHexNumericInput; +CHAR16 *gToggleCheckBox; +CHAR16 *gPromptForData; +CHAR16 *gPromptForPassword; +CHAR16 *gPromptForNewPassword; +CHAR16 *gConfirmPassword; +CHAR16 *gConfirmError; +CHAR16 *gPassowordInvalid; +CHAR16 *gPressEnter; CHAR16 *gEmptyString; -CHAR16 *mUnknownString = L"!"; - -EFI_GUID gZeroGuid = {0, 0, 0, {0, 0, 0, 0, 0, 0, 0, 0}}; - -extern UINT32 gBrowserStatus; -extern CHAR16 *gErrorInfo; -extern EFI_GUID mCurrentFormSetGuid; -extern EFI_HII_HANDLE mCurrentHiiHandle; -extern UINT16 mCurrentFormId; -extern FORM_DISPLAY_ENGINE_FORM gDisplayFormData; - -/** - Create a menu with specified formset GUID and form ID, and add it as a child - of the given parent menu. - - @param HiiHandle Hii handle related to this formset. - @param FormSetGuid The Formset Guid of menu to be added. - @param FormId The Form ID of menu to be added. - @param QuestionId The question id of this menu to be added. - - @return A pointer to the newly added menu or NULL if memory is insufficient. +CHAR16 *gAreYouSure; +CHAR16 *gYesResponse; +CHAR16 *gNoResponse; +CHAR16 *gMiniString; +CHAR16 *gPlusString; +CHAR16 *gMinusString; +CHAR16 *gAdjustNumber; +CHAR16 *gSaveChanges; +CHAR16 *gOptionMismatch; +CHAR16 *gFormSuppress; +CHAR16 *gProtocolNotFound; -**/ -FORM_ENTRY_INFO * -UiAddMenuList ( - IN EFI_HII_HANDLE HiiHandle, - IN EFI_GUID *FormSetGuid, - IN UINT16 FormId, - IN UINT16 QuestionId - ) -{ - FORM_ENTRY_INFO *MenuList; +CHAR16 *mUnknownString = L"!"; - MenuList = AllocateZeroPool (sizeof (FORM_ENTRY_INFO)); - if (MenuList == NULL) { - return NULL; - } +CHAR16 gPromptBlockWidth; +CHAR16 gOptionBlockWidth; +CHAR16 gHelpBlockWidth; - MenuList->Signature = FORM_ENTRY_INFO_SIGNATURE; +EFI_GUID gZeroGuid = {0, 0, 0, {0, 0, 0, 0, 0, 0, 0, 0}}; +EFI_GUID gSetupBrowserGuid = { + 0xab368524, 0xb60c, 0x495b, {0xa0, 0x9, 0x12, 0xe8, 0x5b, 0x1a, 0xea, 0x32} +}; - MenuList->HiiHandle = HiiHandle; - CopyMem (&MenuList->FormSetGuid, FormSetGuid, sizeof (EFI_GUID)); - MenuList->FormId = FormId; - MenuList->QuestionId = QuestionId; +FORM_BROWSER_FORMSET *gOldFormSet = NULL; +FUNCTIION_KEY_SETTING gFunctionKeySettingTable[] = { // - // If parent is not specified, it is the root Form of a Formset + // Boot Manager // - InsertTailList (&mPrivateData.FormBrowserEx2.FormViewHistoryHead, &MenuList->Link); - - return MenuList; -} - -/** - Return the form id for the input hiihandle and formset. - - @param HiiHandle HiiHandle for FormSet. - @param FormSetGuid The Formset GUID of the menu to search. - - @return First form's id for this form set. - -**/ -EFI_FORM_ID -GetFirstFormId ( - IN EFI_HII_HANDLE HiiHandle, - IN EFI_GUID *FormSetGuid - ) -{ - LIST_ENTRY *Link; - FORM_BROWSER_FORM *Form; - - Link = GetFirstNode (&gCurrentSelection->FormSet->FormListHead); - Form = FORM_BROWSER_FORM_FROM_LINK (Link); - - return Form->FormId; -} - -/** - Search Menu with given FormSetGuid and FormId in all cached menu list. - - @param HiiHandle HiiHandle for FormSet. - @param FormSetGuid The Formset GUID of the menu to search. - @param FormId The Form ID of menu to search. - - @return A pointer to menu found or NULL if not found. - -**/ -FORM_ENTRY_INFO * -UiFindMenuList ( - IN EFI_HII_HANDLE HiiHandle, - IN EFI_GUID *FormSetGuid, - IN UINT16 FormId - ) -{ - LIST_ENTRY *Link; - FORM_ENTRY_INFO *MenuList; - FORM_ENTRY_INFO *RetMenu; - EFI_FORM_ID FirstFormId; - - RetMenu = NULL; - - Link = GetFirstNode (&mPrivateData.FormBrowserEx2.FormViewHistoryHead); - while (!IsNull (&mPrivateData.FormBrowserEx2.FormViewHistoryHead, Link)) { - MenuList = FORM_ENTRY_INFO_FROM_LINK (Link); - Link = GetNextNode (&mPrivateData.FormBrowserEx2.FormViewHistoryHead, Link); - - // - // If already find the menu, free the menus behind it. - // - if (RetMenu != NULL) { - RemoveEntryList (&MenuList->Link); - FreePool (MenuList); - continue; - } - - // - // Find the same FromSet. - // - if (MenuList->HiiHandle == HiiHandle) { - if (CompareGuid (&MenuList->FormSetGuid, &gZeroGuid)) { - // - // FormSetGuid is not specified. - // - RetMenu = MenuList; - } else if (CompareGuid (&MenuList->FormSetGuid, FormSetGuid)) { - if (MenuList->FormId == FormId) { - RetMenu = MenuList; - } else if (FormId == 0 || MenuList->FormId == 0 ) { - FirstFormId = GetFirstFormId (HiiHandle, FormSetGuid); - if ((FormId == 0 && FirstFormId == MenuList->FormId) || (MenuList->FormId ==0 && FirstFormId == FormId)) { - RetMenu = MenuList; - } - } + { + { + 0x847bc3fe, + 0xb974, + 0x446d, + { + 0x94, + 0x49, + 0x5a, + 0xd5, + 0x41, + 0x2e, + 0x99, + 0x3b } - } - } - - return RetMenu; -} - -/** - Find parent menu for current menu. - - @param CurrentMenu Current Menu - - @retval The parent menu for current menu. -**/ -FORM_ENTRY_INFO * -UiFindParentMenu ( - IN FORM_ENTRY_INFO *CurrentMenu - ) -{ - FORM_ENTRY_INFO *ParentMenu; - - ParentMenu = NULL; - if (CurrentMenu->Link.BackLink != &mPrivateData.FormBrowserEx2.FormViewHistoryHead) { - ParentMenu = FORM_ENTRY_INFO_FROM_LINK (CurrentMenu->Link.BackLink); - } - - return ParentMenu; -} - -/** - Free Menu list linked list. - - @param MenuListHead One Menu list point in the menu list. - -**/ -VOID -UiFreeMenuList ( - LIST_ENTRY *MenuListHead - ) -{ - FORM_ENTRY_INFO *MenuList; - - while (!IsListEmpty (MenuListHead)) { - MenuList = FORM_ENTRY_INFO_FROM_LINK (MenuListHead->ForwardLink); - RemoveEntryList (&MenuList->Link); - - FreePool (MenuList); - } -} - -/** - Load all hii formset to the browser. - -**/ -VOID -LoadAllHiiFormset ( - VOID - ) -{ - FORM_BROWSER_FORMSET *LocalFormSet; - EFI_HII_HANDLE *HiiHandles; - UINTN Index; - EFI_GUID ZeroGuid; - EFI_STATUS Status; - + }, + NONE_FUNCTION_KEY_SETTING + }, // - // Get all the Hii handles + // Device Manager // - HiiHandles = HiiGetHiiHandles (NULL); - ASSERT (HiiHandles != NULL); - + { + { + 0x3ebfa8e6, + 0x511d, + 0x4b5b, + { + 0xa9, + 0x5f, + 0xfb, + 0x38, + 0x26, + 0xf, + 0x1c, + 0x27 + } + }, + NONE_FUNCTION_KEY_SETTING + }, // - // Search for formset of each class type + // BMM FormSet. // - for (Index = 0; HiiHandles[Index] != NULL; Index++) { - // - // Check HiiHandles[Index] does exist in global maintain list. - // - if (GetFormSetFromHiiHandle (HiiHandles[Index]) != NULL) { - continue; - } - - // - // Initilize FormSet Setting - // - LocalFormSet = AllocateZeroPool (sizeof (FORM_BROWSER_FORMSET)); - ASSERT (LocalFormSet != NULL); - ZeroMem (&ZeroGuid, sizeof (ZeroGuid)); - Status = InitializeFormSet (HiiHandles[Index], &ZeroGuid, LocalFormSet); - if (EFI_ERROR (Status) || IsListEmpty (&LocalFormSet->FormListHead)) { - DestroyFormSet (LocalFormSet); - continue; - } - InitializeCurrentSetting (LocalFormSet); - - // - // Initilize Questions' Value - // - Status = LoadFormSetConfig (NULL, LocalFormSet); - if (EFI_ERROR (Status)) { - DestroyFormSet (LocalFormSet); - continue; - } - } - + { + { + 0x642237c7, + 0x35d4, + 0x472d, + { + 0x83, + 0x65, + 0x12, + 0xe0, + 0xcc, + 0xf2, + 0x7a, + 0x22 + } + }, + NONE_FUNCTION_KEY_SETTING + }, // - // Free resources, and restore gOldFormSet and gClassOfVfr + // BMM File Explorer FormSet. // - FreePool (HiiHandles); -} + { + { + 0x1f2d63e1, + 0xfebd, + 0x4dc7, + { + 0x9c, + 0xc5, + 0xba, + 0x2b, + 0x1c, + 0xef, + 0x9c, + 0x5b + } + }, + NONE_FUNCTION_KEY_SETTING + }, +}; /** This is the routine which an external caller uses to direct the browser @@ -343,14 +229,26 @@ SendForm ( UI_MENU_SELECTION *Selection; UINTN Index; FORM_BROWSER_FORMSET *FormSet; - FORM_ENTRY_INFO *MenuList; + LIST_ENTRY *Link; // - // If EDKII_FORM_DISPLAY_ENGINE_PROTOCOL not found, return EFI_UNSUPPORTED. + // Calculate total number of Register HotKeys. // - if (mFormDisplay == NULL) { - return EFI_UNSUPPORTED; + Index = 0; + Link = GetFirstNode (&gBrowserHotKeyList); + while (!IsNull (&gBrowserHotKeyList, Link)) { + Link = GetNextNode (&gBrowserHotKeyList, Link); + Index ++; } + // + // Show three HotKeys help information on one ROW. + // + gFooterHeight = FOOTER_HEIGHT + (Index / 3); + + // + // Clean the history menu list. + // + InitializeListHead (&gMenuList); // // Save globals used by SendForm() @@ -358,10 +256,65 @@ SendForm ( SaveBrowserContext (); gResetRequired = FALSE; - gExitRequired = FALSE; - Status = EFI_SUCCESS; - gEmptyString = L""; - gDisplayFormData.ScreenDimensions = (EFI_SCREEN_DESCRIPTOR *) ScreenDimensions; + Status = EFI_SUCCESS; + ZeroMem (&gScreenDimensions, sizeof (EFI_SCREEN_DESCRIPTOR)); + + // + // Seed the dimensions in the global + // + gST->ConOut->QueryMode ( + gST->ConOut, + gST->ConOut->Mode->Mode, + &gScreenDimensions.RightColumn, + &gScreenDimensions.BottomRow + ); + + if (ScreenDimensions != NULL) { + // + // Check local dimension vs. global dimension. + // + if ((gScreenDimensions.RightColumn < ScreenDimensions->RightColumn) || + (gScreenDimensions.BottomRow < ScreenDimensions->BottomRow) + ) { + Status = EFI_INVALID_PARAMETER; + goto Done; + } else { + // + // Local dimension validation. + // + if ((ScreenDimensions->RightColumn > ScreenDimensions->LeftColumn) && + (ScreenDimensions->BottomRow > ScreenDimensions->TopRow) && + ((ScreenDimensions->RightColumn - ScreenDimensions->LeftColumn) > 2) && + ( + (ScreenDimensions->BottomRow - ScreenDimensions->TopRow) > STATUS_BAR_HEIGHT + + SCROLL_ARROW_HEIGHT * + 2 + + FRONT_PAGE_HEADER_HEIGHT + + gFooterHeight + + 1 + ) + ) { + CopyMem (&gScreenDimensions, (VOID *) ScreenDimensions, sizeof (EFI_SCREEN_DESCRIPTOR)); + } else { + Status = EFI_INVALID_PARAMETER; + goto Done; + } + } + } + + gOptionBlockWidth = (CHAR16) ((gScreenDimensions.RightColumn - gScreenDimensions.LeftColumn) / 3); + gPromptBlockWidth = (CHAR16) (gOptionBlockWidth + LEFT_SKIPPED_COLUMNS); + gHelpBlockWidth = (CHAR16) (gOptionBlockWidth - LEFT_SKIPPED_COLUMNS); + + // + // Initialize the strings for the browser, upon exit of the browser, the strings will be freed + // + InitializeBrowserStrings (); + + // + // Ensure we are in Text mode + // + gST->ConOut->SetAttribute (gST->ConOut, EFI_TEXT_ATTR (EFI_LIGHTGRAY, EFI_BLACK)); for (Index = 0; Index < HandleCount; Index++) { Selection = AllocateZeroPool (sizeof (UI_MENU_SELECTION)); @@ -382,13 +335,18 @@ SendForm ( // // Initialize internal data structures of FormSet // - Status = InitializeFormSet (Selection->Handle, &Selection->FormSetGuid, FormSet); + Status = InitializeFormSet (Selection->Handle, &Selection->FormSetGuid, FormSet, TRUE); if (EFI_ERROR (Status) || IsListEmpty (&FormSet->FormListHead)) { DestroyFormSet (FormSet); break; } Selection->FormSet = FormSet; + // + // Try to find pre FormSet in the maintain backup list. + // + gOldFormSet = GetFormSetFromHiiHandle (Selection->Handle); + // // Display this formset // @@ -398,34 +356,25 @@ SendForm ( gCurrentSelection = NULL; - // - // If no data is changed, don't need to save current FormSet into the maintain list. - // - if (!IsNvUpdateRequiredForFormSet (FormSet) && !IsStorageDataChangedForFormSet(FormSet)) { - CleanBrowserStorage(FormSet); - RemoveEntryList (&FormSet->Link); - DestroyFormSet (FormSet); - } - if (EFI_ERROR (Status)) { break; } - } while (Selection->Action == UI_ACTION_REFRESH_FORMSET); - - FreePool (Selection); - } - // - // Still has error info, pop up a message. - // - if (gBrowserStatus != BROWSER_SUCCESS) { - gDisplayFormData.BrowserStatus = gBrowserStatus; - gDisplayFormData.ErrorString = gErrorInfo; + } while (Selection->Action == UI_ACTION_REFRESH_FORMSET); - gBrowserStatus = BROWSER_SUCCESS; - gErrorInfo = NULL; + if (gOldFormSet != NULL) { + // + // If no data is changed, don't need to save current FormSet into the maintain list. + // + if (!IsNvUpdateRequired (gOldFormSet)) { + CleanBrowserStorage(gOldFormSet); + RemoveEntryList (&gOldFormSet->Link); + DestroyFormSet (gOldFormSet); + } + gOldFormSet = NULL; + } - mFormDisplay->FormDisplay (&gDisplayFormData, NULL); + FreePool (Selection); } if (ActionRequest != NULL) { @@ -435,17 +384,13 @@ SendForm ( } } - mFormDisplay->ExitDisplay(); + FreeBrowserStrings (); + UiFreeMenuList(&gMenuList); - // - // Clear the menu history data. - // - while (!IsListEmpty (&mPrivateData.FormBrowserEx2.FormViewHistoryHead)) { - MenuList = FORM_ENTRY_INFO_FROM_LINK (mPrivateData.FormBrowserEx2.FormViewHistoryHead.ForwardLink); - RemoveEntryList (&MenuList->Link); - FreePool (MenuList); - } + gST->ConOut->SetAttribute (gST->ConOut, EFI_TEXT_ATTR (EFI_LIGHTGRAY, EFI_BLACK)); + gST->ConOut->ClearScreen (gST->ConOut); +Done: // // Restore globals used by SendForm() // @@ -454,93 +399,10 @@ SendForm ( return Status; } -/** - Get or set data to the storage. - - @param ResultsDataSize The size of the buffer associatedwith ResultsData. - @param ResultsData A string returned from an IFR browser or - equivalent. The results string will have no - routing information in them. - @param RetrieveData A BOOLEAN field which allows an agent to retrieve - (if RetrieveData = TRUE) data from the uncommitted - browser state information or set (if RetrieveData - = FALSE) data in the uncommitted browser state - information. - @param Storage The pointer to the storage. - - @retval EFI_SUCCESS The results have been distributed or are awaiting - distribution. - -**/ -EFI_STATUS -ProcessStorage ( - IN OUT UINTN *ResultsDataSize, - IN OUT EFI_STRING *ResultsData, - IN BOOLEAN RetrieveData, - IN BROWSER_STORAGE *Storage - ) -{ - CHAR16 *ConfigResp; - EFI_STATUS Status; - CHAR16 *StrPtr; - UINTN BufferSize; - UINTN TmpSize; - - if (RetrieveData) { - // - // Generate - // - Status = StorageToConfigResp (Storage, &ConfigResp, Storage->ConfigRequest, TRUE); - if (EFI_ERROR (Status)) { - return Status; - } - - // - // Skip and '&' to point to when first copy the configbody. - // Also need to consider add "\0" at first time. - // - StrPtr = ConfigResp + StrLen (Storage->ConfigHdr) + 1; - BufferSize = StrSize (StrPtr); - - - // - // Copy the data if the input buffer is bigger enough. - // - if (*ResultsDataSize >= BufferSize) { - StrCpy (*ResultsData, StrPtr); - } - - *ResultsDataSize = BufferSize; - FreePool (ConfigResp); - } else { - // - // Prepare - // - TmpSize = StrLen (*ResultsData); - BufferSize = (TmpSize + StrLen (Storage->ConfigHdr) + 2) * sizeof (CHAR16); - ConfigResp = AllocateZeroPool (BufferSize); - ASSERT (ConfigResp != NULL); - - StrCpy (ConfigResp, Storage->ConfigHdr); - StrCat (ConfigResp, L"&"); - StrCat (ConfigResp, *ResultsData); - - // - // Update Browser uncommited data - // - Status = ConfigRespToStorage (Storage, ConfigResp); - FreePool (ConfigResp); - if (EFI_ERROR (Status)) { - return Status; - } - } - - return EFI_SUCCESS; -} /** - This routine called this service in the browser to retrieve or set certain uncommitted - state information that resides in the open formsets. + This function is called by a callback handler to retrieve uncommitted state + data from the browser. @param This A pointer to the EFI_FORM_BROWSER2_PROTOCOL instance. @@ -578,69 +440,60 @@ BrowserCallback ( { EFI_STATUS Status; LIST_ENTRY *Link; - BROWSER_STORAGE *Storage; - FORMSET_STORAGE *FormsetStorage; + FORMSET_STORAGE *Storage; FORM_BROWSER_FORMSET *FormSet; - UINTN TotalSize; BOOLEAN Found; + CHAR16 *ConfigResp; + CHAR16 *StrPtr; + UINTN BufferSize; + UINTN TmpSize; if (ResultsDataSize == NULL || ResultsData == NULL) { return EFI_INVALID_PARAMETER; } - TotalSize = *ResultsDataSize; - Storage = NULL; - Found = FALSE; - Status = EFI_SUCCESS; + if (gCurrentSelection == NULL) { + return EFI_NOT_READY; + } + + Storage = NULL; + ConfigResp = NULL; + FormSet = gCurrentSelection->FormSet; // - // If set browser data, pre load all hii formset to avoid set the varstore which is not - // saved in browser. + // Find target storage // - if (!RetrieveData && (gBrowserSettingScope == SystemLevel)) { - LoadAllHiiFormset(); + Link = GetFirstNode (&FormSet->StorageListHead); + if (IsNull (&FormSet->StorageListHead, Link)) { + return EFI_UNSUPPORTED; } if (VariableGuid != NULL) { // - // Try to find target storage in the current formset. + // Try to find target storage // - Link = GetFirstNode (&gBrowserStorageList); - while (!IsNull (&gBrowserStorageList, Link)) { - Storage = BROWSER_STORAGE_FROM_LINK (Link); - Link = GetNextNode (&gBrowserStorageList, Link); - // - // Check the current storage. - // - if (!CompareGuid (&Storage->Guid, (EFI_GUID *) VariableGuid)) { - continue; - } + Found = FALSE; + while (!IsNull (&FormSet->StorageListHead, Link)) { + Storage = FORMSET_STORAGE_FROM_LINK (Link); + Link = GetNextNode (&FormSet->StorageListHead, Link); - if (Storage->Type == EFI_HII_VARSTORE_BUFFER || - Storage->Type == EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER) { - // - // Buffer storage require both GUID and Name - // - if (VariableName == NULL) { - return EFI_NOT_FOUND; - } + if (CompareGuid (&Storage->BrowserStorage->Guid, (EFI_GUID *) VariableGuid)) { + if (Storage->BrowserStorage->Type == EFI_HII_VARSTORE_BUFFER || + Storage->BrowserStorage->Type == EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER) { + // + // Buffer storage require both GUID and Name + // + if (VariableName == NULL) { + return EFI_NOT_FOUND; + } - if (StrCmp (Storage->Name, (CHAR16 *) VariableName) != 0) { - continue; + if (StrCmp (Storage->BrowserStorage->Name, (CHAR16 *) VariableName) != 0) { + continue; + } } + Found = TRUE; + break; } - - Status = ProcessStorage (&TotalSize, &ResultsData, RetrieveData, Storage); - if (EFI_ERROR (Status)) { - return Status; - } - - // - // Different formsets may have same varstore, so here just set the flag - // not exit the circle. - // - Found = TRUE; - break; } if (!Found) { @@ -650,62 +503,65 @@ BrowserCallback ( // // GUID/Name is not specified, take the first storage in FormSet // - if (gCurrentSelection == NULL) { - return EFI_NOT_READY; - } + Storage = FORMSET_STORAGE_FROM_LINK (Link); + } + if (RetrieveData) { // - // Generate + // Skip if there is no RequestElement // - FormSet = gCurrentSelection->FormSet; - Link = GetFirstNode (&FormSet->StorageListHead); - if (IsNull (&FormSet->StorageListHead, Link)) { - return EFI_UNSUPPORTED; + if (Storage->ElementCount == 0) { + return EFI_SUCCESS; } - FormsetStorage = FORMSET_STORAGE_FROM_LINK (Link); - - Status = ProcessStorage (&TotalSize, &ResultsData, RetrieveData, FormsetStorage->BrowserStorage); + // + // Generate + // + Status = StorageToConfigResp (Storage->BrowserStorage, &ConfigResp, Storage->ConfigRequest); if (EFI_ERROR (Status)) { return Status; } - } - if (RetrieveData) { - Status = TotalSize <= *ResultsDataSize ? EFI_SUCCESS : EFI_BUFFER_TOO_SMALL; - *ResultsDataSize = TotalSize; - } - - return Status; + // + // Skip and '&' to point to + // + StrPtr = ConfigResp + StrLen (Storage->BrowserStorage->ConfigHdr) + 1; -} + BufferSize = StrSize (StrPtr); + if (*ResultsDataSize < BufferSize) { + *ResultsDataSize = BufferSize; + FreePool (ConfigResp); + return EFI_BUFFER_TOO_SMALL; + } -/** - Callback function for SimpleTextInEx protocol install events + *ResultsDataSize = BufferSize; + CopyMem (ResultsData, StrPtr, BufferSize); - @param Event the event that is signaled. - @param Context not used here. + FreePool (ConfigResp); + } else { + // + // Prepare + // + TmpSize = StrLen (ResultsData); + BufferSize = (TmpSize + StrLen (Storage->BrowserStorage->ConfigHdr) + 2) * sizeof (CHAR16); + ConfigResp = AllocateZeroPool (BufferSize); + ASSERT (ConfigResp != NULL); -**/ -VOID -EFIAPI -FormDisplayCallback ( - IN EFI_EVENT Event, - IN VOID *Context - ) -{ - EFI_STATUS Status; + StrCpy (ConfigResp, Storage->BrowserStorage->ConfigHdr); + StrCat (ConfigResp, L"&"); + StrCat (ConfigResp, ResultsData); - if (mFormDisplay != NULL) { - return; + // + // Update Browser uncommited data + // + Status = ConfigRespToStorage (Storage->BrowserStorage, ConfigResp); + if (EFI_ERROR (Status)) { + return Status; + } } - Status = gBS->LocateProtocol ( - &gEdkiiFormDisplayEngineProtocolGuid, - NULL, - (VOID **) &mFormDisplay - ); + return EFI_SUCCESS; } /** @@ -726,7 +582,8 @@ InitializeSetup ( ) { EFI_STATUS Status; - VOID *Registration; + EFI_INPUT_KEY DefaultHotKey; + EFI_STRING HelpString; // // Locate required Hii relative protocols @@ -738,6 +595,13 @@ InitializeSetup ( ); ASSERT_EFI_ERROR (Status); + Status = gBS->LocateProtocol ( + &gEfiHiiStringProtocolGuid, + NULL, + (VOID **) &mHiiString + ); + ASSERT_EFI_ERROR (Status); + Status = gBS->LocateProtocol ( &gEfiHiiConfigRoutingProtocolGuid, NULL, @@ -751,6 +615,30 @@ InitializeSetup ( (VOID **) &mPathFromText ); + // + // Publish our HII data + // + gHiiHandle = HiiAddPackages ( + &gSetupBrowserGuid, + ImageHandle, + SetupBrowserStrings, + NULL + ); + ASSERT (gHiiHandle != NULL); + + // + // Initialize Driver private data + // + gBannerData = AllocateZeroPool (sizeof (BANNER_DATA)); + ASSERT (gBannerData != NULL); + + // + // Initialize generic help strings. + // + gSaveFailed = GetToken (STRING_TOKEN (SAVE_FAILED), gHiiHandle); + gDiscardFailed = GetToken (STRING_TOKEN (DISCARD_FAILED), gHiiHandle); + gDefaultFailed = GetToken (STRING_TOKEN (DEFAULT_FAILED), gHiiHandle); + // // Install FormBrowser2 protocol // @@ -764,18 +652,25 @@ InitializeSetup ( ASSERT_EFI_ERROR (Status); // - // Install FormBrowserEx2 protocol + // Install default HotKey F10 for Save + // + DefaultHotKey.UnicodeChar = CHAR_NULL; + HelpString = GetToken (STRING_TOKEN (FUNCTION_TEN_STRING), gHiiHandle); + DefaultHotKey.ScanCode = SCAN_F10; + RegisterHotKey (&DefaultHotKey, BROWSER_ACTION_SUBMIT, 0, HelpString); + FreePool (HelpString); + // + // Install default HotKey F9 for Reset To Defaults + // + DefaultHotKey.ScanCode = SCAN_F9; + HelpString = GetToken (STRING_TOKEN (FUNCTION_NINE_STRING), gHiiHandle); + RegisterHotKey (&DefaultHotKey, BROWSER_ACTION_DEFAULT, EFI_HII_DEFAULT_CLASS_STANDARD, HelpString); + FreePool (HelpString); + + // + // Install FormBrowserEx protocol // - InitializeListHead (&mPrivateData.FormBrowserEx2.FormViewHistoryHead); mPrivateData.Handle = NULL; - Status = gBS->InstallProtocolInterface ( - &mPrivateData.Handle, - &gEdkiiFormBrowserEx2ProtocolGuid, - EFI_NATIVE_INTERFACE, - &mPrivateData.FormBrowserEx2 - ); - ASSERT_EFI_ERROR (Status); - Status = gBS->InstallProtocolInterface ( &mPrivateData.Handle, &gEfiFormBrowserExProtocolGuid, @@ -784,25 +679,7 @@ InitializeSetup ( ); ASSERT_EFI_ERROR (Status); - InitializeDisplayFormData (); - - Status = gBS->LocateProtocol ( - &gEdkiiFormDisplayEngineProtocolGuid, - NULL, - (VOID **) &mFormDisplay - ); - - if (EFI_ERROR (Status)) { - EfiCreateProtocolNotifyEvent ( - &gEdkiiFormDisplayEngineProtocolGuid, - TPL_CALLBACK, - FormDisplayCallback, - NULL, - &Registration - ); - } - - return EFI_SUCCESS; + return Status; } @@ -927,17 +804,69 @@ NewStringCat ( return; } - TmpSize = StrSize (*Dest); - NewString = AllocateZeroPool (TmpSize + StrSize (Src) - 1); - ASSERT (NewString != NULL); + TmpSize = StrSize (*Dest); + NewString = AllocateZeroPool (TmpSize + StrSize (Src) - 1); + ASSERT (NewString != NULL); + + StrCpy (NewString, *Dest); + StrCat (NewString, Src); + + FreePool (*Dest); + *Dest = NewString; +} + + +/** + Synchronize or restore Storage's Edit copy and Shadow copy. + + @param Storage The Storage to be synchronized. + @param SyncOrRestore Sync the buffer to editbuffer or Restore the + editbuffer to buffer + if TRUE, copy the editbuffer to the buffer. + if FALSE, copy the buffer to the editbuffer. + +**/ +VOID +SynchronizeStorage ( + IN BROWSER_STORAGE *Storage, + IN BOOLEAN SyncOrRestore + ) +{ + LIST_ENTRY *Link; + NAME_VALUE_NODE *Node; + + switch (Storage->Type) { + case EFI_HII_VARSTORE_BUFFER: + case EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER: + if (SyncOrRestore) { + CopyMem (Storage->Buffer, Storage->EditBuffer, Storage->Size); + } else { + CopyMem (Storage->EditBuffer, Storage->Buffer, Storage->Size); + } + break; + + case EFI_HII_VARSTORE_NAME_VALUE: + Link = GetFirstNode (&Storage->NameValueListHead); + while (!IsNull (&Storage->NameValueListHead, Link)) { + Node = NAME_VALUE_NODE_FROM_LINK (Link); - StrCpy (NewString, *Dest); - StrCat (NewString, Src); + if (SyncOrRestore) { + NewStringCpy (&Node->Value, Node->EditValue); + } else { + NewStringCpy (&Node->EditValue, Node->Value); + } - FreePool (*Dest); - *Dest = NewString; + Link = GetNextNode (&Storage->NameValueListHead, Link); + } + break; + + case EFI_HII_VARSTORE_EFI_VARIABLE: + default: + break; + } } + /** Get Value for given Name from a NameValue Storage. @@ -994,7 +923,6 @@ GetValueByName ( @param Name The Name. @param Value The Value to set. @param SetValueTo Whether update editValue or Value. - @param ReturnNode The node use the input name. @retval EFI_SUCCESS Value found for given Name. @retval EFI_NOT_FOUND No such Name found in NameValue storage. @@ -1002,11 +930,10 @@ GetValueByName ( **/ EFI_STATUS SetValueByName ( - IN BROWSER_STORAGE *Storage, - IN CHAR16 *Name, - IN CHAR16 *Value, - IN GET_SET_QUESTION_VALUE_WITH SetValueTo, - OUT NAME_VALUE_NODE **ReturnNode + IN BROWSER_STORAGE *Storage, + IN CHAR16 *Name, + IN CHAR16 *Value, + IN GET_SET_QUESTION_VALUE_WITH SetValueTo ) { LIST_ENTRY *Link; @@ -1037,11 +964,6 @@ SetValueByName ( } else { Node->Value = Buffer; } - - if (ReturnNode != NULL) { - *ReturnNode = Node; - } - return EFI_SUCCESS; } @@ -1058,7 +980,6 @@ SetValueByName ( @param Storage The Storage to be conveted. @param ConfigResp The returned . @param ConfigRequest The ConfigRequest string. - @param GetEditBuf Get the data from editbuffer or buffer. @retval EFI_SUCCESS Convert success. @retval EFI_INVALID_PARAMETER Incorrect storage type. @@ -1068,26 +989,23 @@ EFI_STATUS StorageToConfigResp ( IN BROWSER_STORAGE *Storage, IN CHAR16 **ConfigResp, - IN CHAR16 *ConfigRequest, - IN BOOLEAN GetEditBuf + IN CHAR16 *ConfigRequest ) { EFI_STATUS Status; EFI_STRING Progress; LIST_ENTRY *Link; NAME_VALUE_NODE *Node; - UINT8 *SourceBuf; Status = EFI_SUCCESS; switch (Storage->Type) { case EFI_HII_VARSTORE_BUFFER: case EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER: - SourceBuf = GetEditBuf ? Storage->EditBuffer : Storage->Buffer; Status = mHiiConfigRouting->BlockToConfig ( mHiiConfigRouting, ConfigRequest, - SourceBuf, + Storage->EditBuffer, Storage->Size, ConfigResp, &Progress @@ -1106,11 +1024,7 @@ StorageToConfigResp ( NewStringCat (ConfigResp, L"&"); NewStringCat (ConfigResp, Node->Name); NewStringCat (ConfigResp, L"="); - if (GetEditBuf) { - NewStringCat (ConfigResp, Node->EditValue); - } else { - NewStringCat (ConfigResp, Node->Value); - } + NewStringCat (ConfigResp, Node->EditValue); } Link = GetNextNode (&Storage->NameValueListHead, Link); } @@ -1191,7 +1105,7 @@ ConfigRespToStorage ( if (StrPtr != NULL) { *StrPtr = 0; } - SetValueByName (Storage, Name, Value, GetSetValueWithEditBuffer, NULL); + SetValueByName (Storage, Name, Value, GetSetValueWithEditBuffer); } break; @@ -1617,7 +1531,7 @@ GetQuestionValue ( if (IsBufferStorage) { CopyMem (Storage->EditBuffer + Question->VarStoreInfo.VarOffset, Dst, StorageWidth); } else { - SetValueByName (Storage, Question->VariableName, Value, GetSetValueWithEditBuffer, NULL); + SetValueByName (Storage, Question->VariableName, Value, GetSetValueWithEditBuffer); } if (Result != NULL) { @@ -1667,10 +1581,8 @@ SetQuestionValue ( CHAR16 *TemName; CHAR16 *TemString; UINTN Index; - NAME_VALUE_NODE *Node; Status = EFI_SUCCESS; - Node = NULL; if (SetValueTo >= GetSetValueWithMax) { return EFI_INVALID_PARAMETER; @@ -1805,14 +1717,6 @@ SetQuestionValue ( // CopyMem (Storage->Buffer + Question->VarStoreInfo.VarOffset, Src, StorageWidth); } - // - // Check whether question value has been changed. - // - if (CompareMem (Storage->Buffer + Question->VarStoreInfo.VarOffset, Storage->EditBuffer + Question->VarStoreInfo.VarOffset, StorageWidth) != 0) { - Question->ValueChanged = TRUE; - } else { - Question->ValueChanged = FALSE; - } } else { if (IsString) { // @@ -1844,19 +1748,8 @@ SetQuestionValue ( } } - Status = SetValueByName (Storage, Question->VariableName, Value, SetValueTo, &Node); + Status = SetValueByName (Storage, Question->VariableName, Value, SetValueTo); FreePool (Value); - if (EFI_ERROR (Status)) { - return Status; - } - // - // Check whether question value has been changed. - // - if (StrCmp (Node->Value, Node->EditValue) != 0) { - Question->ValueChanged = TRUE; - } else { - Question->ValueChanged = FALSE; - } } } else if (SetValueTo == GetSetValueWithHiiDriver) { if (Storage->Type == EFI_HII_VARSTORE_BUFFER || Storage->Type == EFI_HII_VARSTORE_NAME_VALUE) { @@ -1975,12 +1868,12 @@ SetQuestionValue ( /** - Perform nosubmitif check for a Form. + Perform inconsistent check for a Form. @param FormSet FormSet data structure. @param Form Form data structure. @param Question The Question to be validated. - @param Type Validation type: NoSubmit + @param Type Validation type: InConsistent or NoSubmit @retval EFI_SUCCESS Form validation pass. @retval other Form validation failed. @@ -1998,9 +1891,12 @@ ValidateQuestion ( LIST_ENTRY *Link; LIST_ENTRY *ListHead; EFI_STRING PopUp; + EFI_INPUT_KEY Key; FORM_EXPRESSION *Expression; - if (Type == EFI_HII_EXPRESSION_NO_SUBMIT_IF) { + if (Type == EFI_HII_EXPRESSION_INCONSISTENT_IF) { + ListHead = &Question->InconsistentListHead; + } else if (Type == EFI_HII_EXPRESSION_NO_SUBMIT_IF) { ListHead = &Question->NoSubmitListHead; } else { return EFI_UNSUPPORTED; @@ -2024,10 +1920,10 @@ ValidateQuestion ( // if (Expression->Error != 0) { PopUp = GetToken (Expression->Error, FormSet->HiiHandle); - if (Type == EFI_HII_EXPRESSION_NO_SUBMIT_IF) { - gBrowserStatus = BROWSER_NO_SUBMIT_IF; - gErrorInfo = PopUp; - } + do { + CreateDialog (4, TRUE, 0, NULL, &Key, gEmptyString, PopUp, gPressEnter, gEmptyString); + } while (Key.UnicodeChar != CHAR_CARRIAGE_RETURN); + FreePool (PopUp); } return EFI_NOT_READY; @@ -2091,8 +1987,7 @@ NoSubmitCheck ( Fill storage's edit copy with settings requested from Configuration Driver. @param FormSet FormSet data structure. - @param Storage The storage which need to sync. - @param ConfigRequest The config request string which used to sync storage. + @param ConfigInfo The config info related to this form. @param SyncOrRestore Sync the buffer to editbuffer or Restore the editbuffer to buffer if TRUE, copy the editbuffer to the buffer. @@ -2102,11 +1997,10 @@ NoSubmitCheck ( **/ EFI_STATUS -SynchronizeStorage ( - IN FORM_BROWSER_FORMSET *FormSet, - OUT BROWSER_STORAGE *Storage, - IN CHAR16 *ConfigRequest, - IN BOOLEAN SyncOrRestore +SynchronizeStorageForForm ( + IN FORM_BROWSER_FORMSET *FormSet, + IN FORM_BROWSER_CONFIG_REQUEST *ConfigInfo, + IN BOOLEAN SyncOrRestore ) { EFI_STATUS Status; @@ -2120,52 +2014,57 @@ SynchronizeStorage ( Status = EFI_SUCCESS; Result = NULL; + if (FormSet->ConfigAccess == NULL && ConfigInfo->Storage->Type != EFI_HII_VARSTORE_NAME_VALUE) { + return EFI_NOT_FOUND; + } - if (Storage->Type == EFI_HII_VARSTORE_BUFFER || - (Storage->Type == EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER)) { - BufferSize = Storage->Size; + if (ConfigInfo->ElementCount == 0) { + // + // Skip if there is no RequestElement + // + return EFI_SUCCESS; + } + + if (ConfigInfo->Storage->Type == EFI_HII_VARSTORE_BUFFER || + (ConfigInfo->Storage->Type == EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER)) { + BufferSize = ConfigInfo->Storage->Size; if (SyncOrRestore) { - Src = Storage->EditBuffer; - Dst = Storage->Buffer; + Src = ConfigInfo->Storage->EditBuffer; + Dst = ConfigInfo->Storage->Buffer; } else { - Src = Storage->Buffer; - Dst = Storage->EditBuffer; + Src = ConfigInfo->Storage->Buffer; + Dst = ConfigInfo->Storage->EditBuffer; } - if (ConfigRequest != NULL) { - Status = mHiiConfigRouting->BlockToConfig( - mHiiConfigRouting, - ConfigRequest, - Src, - BufferSize, - &Result, - &Progress - ); - if (EFI_ERROR (Status)) { - return Status; - } + Status = mHiiConfigRouting->BlockToConfig( + mHiiConfigRouting, + ConfigInfo->ConfigRequest, + Src, + BufferSize, + &Result, + &Progress + ); + if (EFI_ERROR (Status)) { + return Status; + } - Status = mHiiConfigRouting->ConfigToBlock ( - mHiiConfigRouting, - Result, - Dst, - &BufferSize, - &Progress - ); - if (Result != NULL) { - FreePool (Result); - } - } else { - CopyMem (Dst, Src, BufferSize); + Status = mHiiConfigRouting->ConfigToBlock ( + mHiiConfigRouting, + Result, + Dst, + &BufferSize, + &Progress + ); + if (Result != NULL) { + FreePool (Result); } - } else if (Storage->Type == EFI_HII_VARSTORE_NAME_VALUE) { - Link = GetFirstNode (&Storage->NameValueListHead); - while (!IsNull (&Storage->NameValueListHead, Link)) { + } else if (ConfigInfo->Storage->Type == EFI_HII_VARSTORE_NAME_VALUE) { + Link = GetFirstNode (&ConfigInfo->Storage->NameValueListHead); + while (!IsNull (&ConfigInfo->Storage->NameValueListHead, Link)) { Node = NAME_VALUE_NODE_FROM_LINK (Link); - if ((ConfigRequest != NULL && StrStr (ConfigRequest, Node->Name) != NULL) || - (ConfigRequest == NULL)) { + if (StrStr (ConfigInfo->ConfigRequest, Node->Name) != NULL) { if (SyncOrRestore) { NewStringCpy (&Node->Value, Node->EditValue); } else { @@ -2173,7 +2072,7 @@ SynchronizeStorage ( } } - Link = GetNextNode (&Storage->NameValueListHead, Link); + Link = GetNextNode (&ConfigInfo->Storage->NameValueListHead, Link); } } @@ -2196,9 +2095,20 @@ SendDiscardInfoToDriver ( { LIST_ENTRY *Link; FORM_BROWSER_STATEMENT *Question; + EFI_STATUS Status; + EFI_HII_VALUE HiiValue; + UINT8 *BufferValue; + BOOLEAN ValueChanged; EFI_IFR_TYPE_VALUE *TypeValue; EFI_BROWSER_ACTION_REQUEST ActionRequest; + ValueChanged = FALSE; + BufferValue = NULL; + + if(!Form->NvUpdateRequired) { + return; + } + Link = GetFirstNode (&Form->StatementListHead); while (!IsNull (&Form->StatementListHead, Link)) { Question = FORM_BROWSER_STATEMENT_FROM_LINK (Link); @@ -2212,10 +2122,45 @@ SendDiscardInfoToDriver ( continue; } - if (!Question->ValueChanged) { + if (Question->BufferValue != NULL) { + BufferValue = AllocateZeroPool (Question->StorageWidth); + ASSERT (BufferValue != NULL); + CopyMem (BufferValue, Question->BufferValue, Question->StorageWidth); + } else { + HiiValue.Type = Question->HiiValue.Type; + CopyMem (&HiiValue.Value, &Question->HiiValue.Value, sizeof (EFI_IFR_TYPE_VALUE)); + } + + Status = GetQuestionValue (FormSet, Form, Question, GetSetValueWithBuffer); + if (EFI_ERROR (Status)) { + if (BufferValue != NULL) { + FreePool (BufferValue); + BufferValue = NULL; + } + continue; + } + + if (Question->BufferValue != NULL) { + if (CompareMem (BufferValue, Question->BufferValue, Question->StorageWidth)) { + ValueChanged = TRUE; + } + } else { + if (CompareMem (&HiiValue.Value, &Question->HiiValue.Value, sizeof (EFI_IFR_TYPE_VALUE))) { + ValueChanged = TRUE; + } + } + + if (BufferValue != NULL) { + FreePool (BufferValue); + BufferValue = NULL; + } + + if (!ValueChanged) { continue; } + ValueChanged = FALSE; + if (Question->HiiValue.Type == EFI_IFR_TYPE_BUFFER) { TypeValue = (EFI_IFR_TYPE_VALUE *) Question->BufferValue; } else { @@ -2280,78 +2225,6 @@ ValidateFormSet ( return Find; } -/** - Check whether need to enable the reset flag in form level. - Also clean all ValueChanged flag in question. - - @param SetFlag Whether need to set the Reset Flag. - @param Form Form data structure. - -**/ -VOID -UpdateFlagForForm ( - IN BOOLEAN SetFlag, - IN FORM_BROWSER_FORM *Form - ) -{ - LIST_ENTRY *Link; - FORM_BROWSER_STATEMENT *Question; - BOOLEAN FindOne; - - FindOne = FALSE; - Link = GetFirstNode (&Form->StatementListHead); - while (!IsNull (&Form->StatementListHead, Link)) { - Question = FORM_BROWSER_STATEMENT_FROM_LINK (Link); - - if (SetFlag && Question->ValueChanged && ((Question->QuestionFlags & EFI_IFR_FLAG_RESET_REQUIRED) != 0)) { - gResetRequired = TRUE; - } - - if (Question->ValueChanged) { - Question->ValueChanged = FALSE; - } - - Link = GetNextNode (&Form->StatementListHead, Link); - } -} - -/** - Check whether need to enable the reset flag. - Also clean ValueChanged flag for all statements. - - Form level or formset level, only one. - - @param SetFlag Whether need to set the Reset Flag. - @param FormSet FormSet data structure. - @param Form Form data structure. - -**/ -VOID -ValueChangeResetFlagUpdate ( - IN BOOLEAN SetFlag, - IN FORM_BROWSER_FORMSET *FormSet, - IN FORM_BROWSER_FORM *Form - ) -{ - FORM_BROWSER_FORM *CurrentForm; - LIST_ENTRY *Link; - - // - // Form != NULL means only check form level. - // - if (Form != NULL) { - UpdateFlagForForm(SetFlag, Form); - return; - } - - Link = GetFirstNode (&FormSet->FormListHead); - while (!IsNull (&FormSet->FormListHead, Link)) { - CurrentForm = FORM_BROWSER_FORM_FROM_LINK (Link); - Link = GetNextNode (&FormSet->FormListHead, Link); - - UpdateFlagForForm(SetFlag, CurrentForm); - } -} /** Discard data based on the input setting scope (Form, FormSet or System). @@ -2383,7 +2256,7 @@ DiscardForm ( return EFI_UNSUPPORTED; } - if (SettingScope == FormLevel && IsNvUpdateRequiredForForm (Form)) { + if (SettingScope == FormLevel && Form->NvUpdateRequired) { ConfigInfo = NULL; Link = GetFirstNode (&Form->ConfigRequestHead); while (!IsNull (&Form->ConfigRequestHead, Link)) { @@ -2404,7 +2277,7 @@ DiscardForm ( // // Prepare // - SynchronizeStorage(FormSet, ConfigInfo->Storage, ConfigInfo->ConfigRequest, FALSE); + SynchronizeStorageForForm(FormSet, ConfigInfo, FALSE); // // Call callback with Changed type to inform the driver. @@ -2412,8 +2285,8 @@ DiscardForm ( SendDiscardInfoToDriver (FormSet, Form); } - ValueChangeResetFlagUpdate (FALSE, NULL, Form); - } else if (SettingScope == FormSetLevel && IsNvUpdateRequiredForFormSet (FormSet)) { + Form->NvUpdateRequired = FALSE; + } else if (SettingScope == FormSetLevel && IsNvUpdateRequired(FormSet)) { // // Discard Buffer storage or Name/Value storage @@ -2434,7 +2307,7 @@ DiscardForm ( continue; } - SynchronizeStorage(FormSet, Storage->BrowserStorage, Storage->ConfigRequest, FALSE); + SynchronizeStorage(Storage->BrowserStorage, FALSE); } Link = GetFirstNode (&FormSet->FormListHead); @@ -2448,7 +2321,7 @@ DiscardForm ( SendDiscardInfoToDriver (FormSet, Form); } - ValueChangeResetFlagUpdate(FALSE, FormSet, NULL); + UpdateNvInfoInForm (FormSet, FALSE); } else if (SettingScope == SystemLevel) { // // System Level Discard. @@ -2528,7 +2401,7 @@ SubmitForm ( return Status; } - if (SettingScope == FormLevel && IsNvUpdateRequiredForForm (Form)) { + if (SettingScope == FormLevel && Form->NvUpdateRequired) { ConfigInfo = NULL; Link = GetFirstNode (&Form->ConfigRequestHead); while (!IsNull (&Form->ConfigRequestHead, Link)) { @@ -2550,7 +2423,7 @@ SubmitForm ( // // 1. Prepare // - Status = StorageToConfigResp (ConfigInfo->Storage, &ConfigResp, ConfigInfo->ConfigRequest, TRUE); + Status = StorageToConfigResp (ConfigInfo->Storage, &ConfigResp, ConfigInfo->ConfigRequest); if (EFI_ERROR (Status)) { return Status; } @@ -2626,14 +2499,14 @@ SubmitForm ( // // 3. Config success, update storage shadow Buffer, only update the data belong to this form. // - SynchronizeStorage (FormSet, ConfigInfo->Storage, ConfigInfo->ConfigRequest, TRUE); + SynchronizeStorageForForm(FormSet, ConfigInfo, TRUE); } // // 4. Update the NV flag. // - ValueChangeResetFlagUpdate(TRUE, NULL, Form); - } else if (SettingScope == FormSetLevel && IsNvUpdateRequiredForFormSet (FormSet)) { + Form->NvUpdateRequired = FALSE; + } else if (SettingScope == FormSetLevel && IsNvUpdateRequired(FormSet)) { // // Submit Buffer storage or Name/Value storage // @@ -2657,7 +2530,7 @@ SubmitForm ( // // 1. Prepare // - Status = StorageToConfigResp (Storage, &ConfigResp, FormSetStorage->ConfigRequest, TRUE); + Status = StorageToConfigResp (Storage, &ConfigResp, FormSetStorage->ConfigRequest); if (EFI_ERROR (Status)) { return Status; } @@ -2729,13 +2602,13 @@ SubmitForm ( // // 3. Config success, update storage shadow Buffer // - SynchronizeStorage (FormSet, Storage, FormSetStorage->ConfigRequest, TRUE); + SynchronizeStorage (Storage, TRUE); } // // 4. Update the NV flag. // - ValueChangeResetFlagUpdate(TRUE, FormSet, NULL); + UpdateNvInfoInForm (FormSet, FALSE); } else if (SettingScope == SystemLevel) { // // System Level Save. @@ -2931,198 +2804,66 @@ GetDefaultValueFromAltCfg ( // // Add tailing L'\0' character // - StringPtr[Index/4] = L'\0'; - } else { - ZeroMem (TemStr, sizeof (TemStr)); - for (Index = 0; Index < LengthStr; Index ++) { - TemStr[0] = Value[LengthStr - Index - 1]; - DigitUint8 = (UINT8) StrHexToUint64 (TemStr); - if ((Index & 1) == 0) { - Dst [Index/2] = DigitUint8; - } else { - Dst [Index/2] = (UINT8) ((DigitUint8 << 4) + Dst [Index/2]); - } - } - } - -Done: - if (ConfigRequest != NULL){ - FreePool (ConfigRequest); - } - - if (ConfigResp != NULL) { - FreePool (ConfigResp); - } - - if (Result != NULL) { - FreePool (Result); - } - - return Status; -} - -/** - Get default Id value used for browser. - - @param DefaultId The default id value used by hii. - - @retval Browser used default value. - -**/ -INTN -GetDefaultIdForCallBack ( - UINTN DefaultId - ) -{ - if (DefaultId == EFI_HII_DEFAULT_CLASS_STANDARD) { - return EFI_BROWSER_ACTION_DEFAULT_STANDARD; - } else if (DefaultId == EFI_HII_DEFAULT_CLASS_MANUFACTURING) { - return EFI_BROWSER_ACTION_DEFAULT_MANUFACTURING; - } else if (DefaultId == EFI_HII_DEFAULT_CLASS_SAFE) { - return EFI_BROWSER_ACTION_DEFAULT_SAFE; - } else if (DefaultId >= EFI_HII_DEFAULT_CLASS_PLATFORM_BEGIN && DefaultId < EFI_HII_DEFAULT_CLASS_PLATFORM_BEGIN + 0x1000) { - return EFI_BROWSER_ACTION_DEFAULT_PLATFORM + DefaultId - EFI_HII_DEFAULT_CLASS_PLATFORM_BEGIN; - } else if (DefaultId >= EFI_HII_DEFAULT_CLASS_HARDWARE_BEGIN && DefaultId < EFI_HII_DEFAULT_CLASS_HARDWARE_BEGIN + 0x1000) { - return EFI_BROWSER_ACTION_DEFAULT_HARDWARE + DefaultId - EFI_HII_DEFAULT_CLASS_HARDWARE_BEGIN; - } else if (DefaultId >= EFI_HII_DEFAULT_CLASS_FIRMWARE_BEGIN && DefaultId < EFI_HII_DEFAULT_CLASS_FIRMWARE_BEGIN + 0x1000) { - return EFI_BROWSER_ACTION_DEFAULT_FIRMWARE + DefaultId - EFI_HII_DEFAULT_CLASS_FIRMWARE_BEGIN; - } else { - return -1; - } -} - - - -/** - Return data element in an Array by its Index. - - @param Array The data array. - @param Type Type of the data in this array. - @param Index Zero based index for data in this array. - - @retval Value The data to be returned - -**/ -UINT64 -GetArrayData ( - IN VOID *Array, - IN UINT8 Type, - IN UINTN Index - ) -{ - UINT64 Data; - - ASSERT (Array != NULL); - - Data = 0; - switch (Type) { - case EFI_IFR_TYPE_NUM_SIZE_8: - Data = (UINT64) *(((UINT8 *) Array) + Index); - break; - - case EFI_IFR_TYPE_NUM_SIZE_16: - Data = (UINT64) *(((UINT16 *) Array) + Index); - break; - - case EFI_IFR_TYPE_NUM_SIZE_32: - Data = (UINT64) *(((UINT32 *) Array) + Index); - break; - - case EFI_IFR_TYPE_NUM_SIZE_64: - Data = (UINT64) *(((UINT64 *) Array) + Index); - break; - - default: - break; - } - - return Data; -} - - -/** - Set value of a data element in an Array by its Index. - - @param Array The data array. - @param Type Type of the data in this array. - @param Index Zero based index for data in this array. - @param Value The value to be set. - -**/ -VOID -SetArrayData ( - IN VOID *Array, - IN UINT8 Type, - IN UINTN Index, - IN UINT64 Value - ) -{ - - ASSERT (Array != NULL); - - switch (Type) { - case EFI_IFR_TYPE_NUM_SIZE_8: - *(((UINT8 *) Array) + Index) = (UINT8) Value; - break; - - case EFI_IFR_TYPE_NUM_SIZE_16: - *(((UINT16 *) Array) + Index) = (UINT16) Value; - break; - - case EFI_IFR_TYPE_NUM_SIZE_32: - *(((UINT32 *) Array) + Index) = (UINT32) Value; - break; + StringPtr[Index/4] = L'\0'; + } else { + ZeroMem (TemStr, sizeof (TemStr)); + for (Index = 0; Index < LengthStr; Index ++) { + TemStr[0] = Value[LengthStr - Index - 1]; + DigitUint8 = (UINT8) StrHexToUint64 (TemStr); + if ((Index & 1) == 0) { + Dst [Index/2] = DigitUint8; + } else { + Dst [Index/2] = (UINT8) ((DigitUint8 << 4) + Dst [Index/2]); + } + } + } - case EFI_IFR_TYPE_NUM_SIZE_64: - *(((UINT64 *) Array) + Index) = (UINT64) Value; - break; +Done: + if (ConfigRequest != NULL){ + FreePool (ConfigRequest); + } - default: - break; + if (ConfigResp != NULL) { + FreePool (ConfigResp); + } + + if (Result != NULL) { + FreePool (Result); } + + return Status; } /** - Search an Option of a Question by its value. + Get default Id value used for browser. - @param Question The Question - @param OptionValue Value for Option to be searched. + @param DefaultId The default id value used by hii. - @retval Pointer Pointer to the found Option. - @retval NULL Option not found. + @retval Browser used default value. **/ -QUESTION_OPTION * -ValueToOption ( - IN FORM_BROWSER_STATEMENT *Question, - IN EFI_HII_VALUE *OptionValue +INTN +GetDefaultIdForCallBack ( + UINTN DefaultId ) -{ - LIST_ENTRY *Link; - QUESTION_OPTION *Option; - INTN Result; - - Link = GetFirstNode (&Question->OptionListHead); - while (!IsNull (&Question->OptionListHead, Link)) { - Option = QUESTION_OPTION_FROM_LINK (Link); - - if ((CompareHiiValue (&Option->Value, OptionValue, &Result, NULL) == EFI_SUCCESS) && (Result == 0)) { - // - // Check the suppressif condition, only a valid option can be return. - // - if ((Option->SuppressExpression == NULL) || - ((EvaluateExpressionList(Option->SuppressExpression, FALSE, NULL, NULL) == ExpressFalse))) { - return Option; - } - } - - Link = GetNextNode (&Question->OptionListHead, Link); +{ + if (DefaultId == EFI_HII_DEFAULT_CLASS_STANDARD) { + return EFI_BROWSER_ACTION_DEFAULT_STANDARD; + } else if (DefaultId == EFI_HII_DEFAULT_CLASS_MANUFACTURING) { + return EFI_BROWSER_ACTION_DEFAULT_MANUFACTURING; + } else if (DefaultId == EFI_HII_DEFAULT_CLASS_SAFE) { + return EFI_BROWSER_ACTION_DEFAULT_SAFE; + } else if (DefaultId >= EFI_HII_DEFAULT_CLASS_PLATFORM_BEGIN && DefaultId < EFI_HII_DEFAULT_CLASS_PLATFORM_BEGIN + 0x1000) { + return EFI_BROWSER_ACTION_DEFAULT_PLATFORM + DefaultId - EFI_HII_DEFAULT_CLASS_PLATFORM_BEGIN; + } else if (DefaultId >= EFI_HII_DEFAULT_CLASS_HARDWARE_BEGIN && DefaultId < EFI_HII_DEFAULT_CLASS_HARDWARE_BEGIN + 0x1000) { + return EFI_BROWSER_ACTION_DEFAULT_HARDWARE + DefaultId - EFI_HII_DEFAULT_CLASS_HARDWARE_BEGIN; + } else if (DefaultId >= EFI_HII_DEFAULT_CLASS_FIRMWARE_BEGIN && DefaultId < EFI_HII_DEFAULT_CLASS_FIRMWARE_BEGIN + 0x1000) { + return EFI_BROWSER_ACTION_DEFAULT_FIRMWARE + DefaultId - EFI_HII_DEFAULT_CLASS_FIRMWARE_BEGIN; + } else { + return -1; } - - return NULL; } - /** Reset Question to its default value. @@ -3414,7 +3155,11 @@ ExtractDefault ( LIST_ENTRY *FormLink; LIST_ENTRY *Link; FORM_BROWSER_STATEMENT *Question; + FORM_BROWSER_FORMSET *BackUpFormSet; FORM_BROWSER_FORMSET *LocalFormSet; + EFI_HII_HANDLE *HiiHandles; + UINTN Index; + EFI_GUID ZeroGuid; Status = EFI_SUCCESS; @@ -3484,6 +3229,10 @@ ExtractDefault ( if ((Question->Storage != NULL) && (Question->Storage->Type != EFI_HII_VARSTORE_EFI_VARIABLE)) { SetQuestionValue (FormSet, Form, Question, GetSetValueWithEditBuffer); + // + // Update Form NV flag. + // + Form->NvUpdateRequired = TRUE; } } } else if (SettingScope == FormSetLevel) { @@ -3495,9 +3244,65 @@ ExtractDefault ( } } else if (SettingScope == SystemLevel) { // - // Preload all Hii formset. + // Open all FormSet by locate HII packages. + // Initiliaze the maintain FormSet to store default data as back up data. + // + BackUpFormSet = gOldFormSet; + gOldFormSet = NULL; + + // + // Get all the Hii handles + // + HiiHandles = HiiGetHiiHandles (NULL); + ASSERT (HiiHandles != NULL); + + // + // Search for formset of each class type + // + for (Index = 0; HiiHandles[Index] != NULL; Index++) { + // + // Check HiiHandles[Index] does exist in global maintain list. + // + if (GetFormSetFromHiiHandle (HiiHandles[Index]) != NULL) { + continue; + } + + // + // Initilize FormSet Setting + // + LocalFormSet = AllocateZeroPool (sizeof (FORM_BROWSER_FORMSET)); + ASSERT (LocalFormSet != NULL); + ZeroMem (&ZeroGuid, sizeof (ZeroGuid)); + Status = InitializeFormSet (HiiHandles[Index], &ZeroGuid, LocalFormSet, FALSE); + if (EFI_ERROR (Status) || IsListEmpty (&LocalFormSet->FormListHead)) { + DestroyFormSet (LocalFormSet); + continue; + } + Status = InitializeCurrentSetting (LocalFormSet); + if (EFI_ERROR (Status)) { + DestroyFormSet (LocalFormSet); + continue; + } + // + // Initilize Questions' Value + // + Status = LoadFormSetConfig (NULL, LocalFormSet); + if (EFI_ERROR (Status)) { + DestroyFormSet (LocalFormSet); + continue; + } + + // + // Add FormSet into the maintain list. + // + InsertTailList (&gBrowserFormSetList, &LocalFormSet->Link); + } + + // + // Free resources, and restore gOldFormSet and gClassOfVfr // - LoadAllHiiFormset(); + FreePool (HiiHandles); + gOldFormSet = BackUpFormSet; // // Set Default Value for each FormSet in the maintain list. @@ -3516,81 +3321,6 @@ ExtractDefault ( return EFI_SUCCESS; } - -/** - Validate whether this question's value has changed. - - @param FormSet FormSet data structure. - @param Form Form data structure. - @param Question Question to be initialized. - @param GetValueFrom Where to get value, may from editbuffer, buffer or hii driver. - - @retval TRUE Question's value has changed. - @retval FALSE Question's value has not changed - -**/ -BOOLEAN -IsQuestionValueChanged ( - IN FORM_BROWSER_FORMSET *FormSet, - IN FORM_BROWSER_FORM *Form, - IN OUT FORM_BROWSER_STATEMENT *Question, - IN GET_SET_QUESTION_VALUE_WITH GetValueFrom - ) -{ - EFI_HII_VALUE BackUpValue; - CHAR8 *BackUpBuffer; - EFI_STATUS Status; - BOOLEAN ValueChanged; - UINTN BufferWidth; - - // - // For quetion without storage, always mark it as data not changed. - // - if (Question->Storage == NULL && Question->Operand != EFI_IFR_TIME_OP && Question->Operand != EFI_IFR_DATE_OP) { - return FALSE; - } - - BackUpBuffer = NULL; - ValueChanged = FALSE; - - switch (Question->Operand) { - case EFI_IFR_ORDERED_LIST_OP: - BufferWidth = Question->StorageWidth; - BackUpBuffer = AllocateCopyPool (BufferWidth, Question->BufferValue); - ASSERT (BackUpBuffer != NULL); - break; - - case EFI_IFR_STRING_OP: - case EFI_IFR_PASSWORD_OP: - BufferWidth = (UINTN) Question->Maximum * sizeof (CHAR16); - BackUpBuffer = AllocateCopyPool (BufferWidth, Question->BufferValue); - ASSERT (BackUpBuffer != NULL); - break; - - default: - BufferWidth = 0; - break; - } - CopyMem (&BackUpValue, &Question->HiiValue, sizeof (EFI_HII_VALUE)); - - Status = GetQuestionValue (FormSet, Form, Question, GetValueFrom); - ASSERT_EFI_ERROR(Status); - - if (CompareMem (&BackUpValue, &Question->HiiValue, sizeof (EFI_HII_VALUE)) != 0 || - CompareMem (BackUpBuffer, Question->BufferValue, BufferWidth) != 0) { - ValueChanged = TRUE; - } - - CopyMem (&Question->HiiValue, &BackUpValue, sizeof (EFI_HII_VALUE)); - CopyMem (Question->BufferValue, BackUpBuffer, BufferWidth); - - if (BackUpBuffer != NULL) { - FreePool (BackUpBuffer); - } - - return ValueChanged; -} - /** Initialize Question's Edit copy from Storage. @@ -3624,11 +3354,7 @@ LoadFormConfig ( // // Initialize local copy of Value for each Question // - if (Question->Operand == EFI_IFR_PASSWORD_OP && (Question->QuestionFlags & EFI_IFR_FLAG_CALLBACK)== 0) { - Status = GetQuestionValue (FormSet, Form, Question, GetSetValueWithHiiDriver); - } else { - Status = GetQuestionValue (FormSet, Form, Question, GetSetValueWithEditBuffer); - } + Status = GetQuestionValue (FormSet, Form, Question, GetSetValueWithEditBuffer); if (EFI_ERROR (Status)) { return Status; } @@ -3668,11 +3394,6 @@ LoadFormConfig ( Status = ProcessCallBackFunction(Selection, Question, EFI_BROWSER_ACTION_RETRIEVE, TRUE); } - // - // Update Question Value changed flag. - // - Question->ValueChanged = IsQuestionValueChanged(FormSet, Form, Question, GetSetValueWithBuffer); - Link = GetNextNode (&Form->StatementListHead, Link); } @@ -3716,11 +3437,6 @@ LoadFormSetConfig ( Link = GetNextNode (&FormSet->FormListHead, Link); } - // - // Finished question initialization. - // - FormSet->QuestionInited = TRUE; - return EFI_SUCCESS; } @@ -3775,13 +3491,6 @@ RemoveConfigRequest ( CHAR16 *NextRequestElement; CHAR16 *SearchKey; - // - // No request element in it, just return. - // - if (ConfigRequest == NULL) { - return; - } - if (Storage->Type == EFI_HII_VARSTORE_NAME_VALUE) { // // "&Name1&Name2" section for EFI_HII_VARSTORE_NAME_VALUE storage @@ -3856,7 +3565,6 @@ CleanBrowserStorage ( { LIST_ENTRY *Link; FORMSET_STORAGE *Storage; - CHAR16 *ConfigRequest; Link = GetFirstNode (&FormSet->StorageListHead); while (!IsNull (&FormSet->StorageListHead, Link)) { @@ -3864,8 +3572,7 @@ CleanBrowserStorage ( Link = GetNextNode (&FormSet->StorageListHead, Link); if ((Storage->BrowserStorage->Type != EFI_HII_VARSTORE_BUFFER) && - (Storage->BrowserStorage->Type != EFI_HII_VARSTORE_NAME_VALUE) && - (Storage->BrowserStorage->Type != EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER)) { + (Storage->BrowserStorage->Type != EFI_HII_VARSTORE_NAME_VALUE)) { continue; } @@ -3873,8 +3580,7 @@ CleanBrowserStorage ( continue; } - ConfigRequest = FormSet->QuestionInited ? Storage->ConfigRequest : Storage->ConfigElements; - RemoveConfigRequest (Storage->BrowserStorage, ConfigRequest); + RemoveConfigRequest (Storage->BrowserStorage, Storage->ConfigRequest); } } @@ -3945,6 +3651,7 @@ AppendConfigRequest ( Adjust the config request info, remove the request elements which already in AllConfigRequest string. @param Storage Form set Storage. + @param ConfigRequest Return the ConfigRequest info. @retval TRUE Has element not covered by current used elements, need to continue to call ExtractConfig @retval FALSE All elements covered by current used elements. @@ -3952,7 +3659,8 @@ AppendConfigRequest ( **/ BOOLEAN ConfigRequestAdjust ( - IN FORMSET_STORAGE *Storage + IN FORMSET_STORAGE *Storage, + OUT CHAR16 **ConfigRequest ) { CHAR16 *RequestElement; @@ -3968,10 +3676,7 @@ ConfigRequestAdjust ( if (Storage->BrowserStorage->ConfigRequest == NULL) { Storage->BrowserStorage->ConfigRequest = AllocateCopyPool (StrSize (Storage->ConfigRequest), Storage->ConfigRequest); - if (Storage->ConfigElements != NULL) { - FreePool (Storage->ConfigElements); - } - Storage->ConfigElements = AllocateCopyPool (StrSize (Storage->ConfigRequest), Storage->ConfigRequest); + *ConfigRequest = AllocateCopyPool (StrSize (Storage->ConfigRequest), Storage->ConfigRequest); return TRUE; } @@ -4040,10 +3745,7 @@ ConfigRequestAdjust ( } if (RetVal) { - if (Storage->ConfigElements != NULL) { - FreePool (Storage->ConfigElements); - } - Storage->ConfigElements = RetBuf; + *ConfigRequest = RetBuf; } else { FreePool (RetBuf); } @@ -4051,163 +3753,16 @@ ConfigRequestAdjust ( return RetVal; } -/** - - Base on ConfigRequest info to get default value for current formset. - - ConfigRequest info include the info about which questions in current formset need to - get default value. This function only get these questions default value. - - @param FormSet FormSet data structure. - @param Storage Storage need to update value. - @param ConfigRequest The config request string. - -**/ -VOID -GetDefaultForFormset ( - IN FORM_BROWSER_FORMSET *FormSet, - IN BROWSER_STORAGE *Storage, - IN CHAR16 *ConfigRequest - ) -{ - UINT8 *BackUpBuf; - UINTN BufferSize; - LIST_ENTRY BackUpList; - NAME_VALUE_NODE *Node; - LIST_ENTRY *Link; - LIST_ENTRY *NodeLink; - NAME_VALUE_NODE *TmpNode; - EFI_STATUS Status; - EFI_STRING Progress; - EFI_STRING Result; - - BackUpBuf = NULL; - InitializeListHead(&BackUpList); - - // - // Back update the edit buffer. - // - if (Storage->Type == EFI_HII_VARSTORE_BUFFER || - (Storage->Type == EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER)) { - BackUpBuf = AllocateCopyPool (Storage->Size, Storage->EditBuffer); - ASSERT (BackUpBuf != NULL); - } else if (Storage->Type == EFI_HII_VARSTORE_NAME_VALUE) { - Link = GetFirstNode (&Storage->NameValueListHead); - while (!IsNull (&Storage->NameValueListHead, Link)) { - Node = NAME_VALUE_NODE_FROM_LINK (Link); - Link = GetNextNode (&Storage->NameValueListHead, Link); - - // - // Only back Node belong to this formset. - // - if (StrStr (Storage->ConfigRequest, Node->Name) == NULL) { - continue; - } - - TmpNode = AllocateCopyPool (sizeof (NAME_VALUE_NODE), Node); - TmpNode->Name = AllocateCopyPool (StrSize(Node->Name) * sizeof (CHAR16), Node->Name); - TmpNode->EditValue = AllocateCopyPool (StrSize(Node->EditValue) * sizeof (CHAR16), Node->EditValue); - - InsertTailList(&BackUpList, &TmpNode->Link); - } - } - - // - // Get default value. - // - ExtractDefault (FormSet, NULL, EFI_HII_DEFAULT_CLASS_STANDARD, FormSetLevel, GetDefaultForStorage, Storage, TRUE); - - // - // Update the question value based on the input ConfigRequest. - // - if (Storage->Type == EFI_HII_VARSTORE_BUFFER || - (Storage->Type == EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER)) { - ASSERT (BackUpBuf != NULL); - BufferSize = Storage->Size; - Status = mHiiConfigRouting->BlockToConfig( - mHiiConfigRouting, - ConfigRequest, - Storage->EditBuffer, - BufferSize, - &Result, - &Progress - ); - ASSERT_EFI_ERROR (Status); - - Status = mHiiConfigRouting->ConfigToBlock ( - mHiiConfigRouting, - Result, - BackUpBuf, - &BufferSize, - &Progress - ); - ASSERT_EFI_ERROR (Status); - - if (Result != NULL) { - FreePool (Result); - } - - CopyMem (Storage->EditBuffer, BackUpBuf, Storage->Size); - FreePool (BackUpBuf); - } else if (Storage->Type == EFI_HII_VARSTORE_NAME_VALUE) { - // - // Update question value, only element in ConfigReqeust will be update. - // - Link = GetFirstNode (&BackUpList); - while (!IsNull (&BackUpList, Link)) { - Node = NAME_VALUE_NODE_FROM_LINK (Link); - Link = GetNextNode (&BackUpList, Link); - - if (StrStr (ConfigRequest, Node->Name) != NULL) { - continue; - } - - NodeLink = GetFirstNode (&Storage->NameValueListHead); - while (!IsNull (&Storage->NameValueListHead, NodeLink)) { - TmpNode = NAME_VALUE_NODE_FROM_LINK (NodeLink); - NodeLink = GetNextNode (&Storage->NameValueListHead, NodeLink); - - if (StrCmp (Node->Name, TmpNode->Name) != 0) { - continue; - } - - FreePool (TmpNode->EditValue); - TmpNode->EditValue = AllocateCopyPool (StrSize(Node->EditValue) * sizeof (CHAR16), Node->EditValue); - - RemoveEntryList (&Node->Link); - FreePool (Node->EditValue); - FreePool (Node->Name); - FreePool (Node); - } - } - - // - // Restore the Name/Value node. - // - Link = GetFirstNode (&BackUpList); - while (!IsNull (&BackUpList, Link)) { - Node = NAME_VALUE_NODE_FROM_LINK (Link); - Link = GetNextNode (&BackUpList, Link); - - // - // Free this node. - // - RemoveEntryList (&Node->Link); - FreePool (Node->EditValue); - FreePool (Node->Name); - FreePool (Node); - } - } -} - /** Fill storage's edit copy with settings requested from Configuration Driver. @param FormSet FormSet data structure. @param Storage Buffer Storage. + @retval EFI_SUCCESS The function completed successfully. + **/ -VOID +EFI_STATUS LoadStorage ( IN FORM_BROWSER_FORMSET *FormSet, IN FORMSET_STORAGE *Storage @@ -4217,17 +3772,18 @@ LoadStorage ( EFI_STRING Progress; EFI_STRING Result; CHAR16 *StrPtr; + CHAR16 *ConfigRequest; - switch (Storage->BrowserStorage->Type) { - case EFI_HII_VARSTORE_EFI_VARIABLE: - return; - - case EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER: - if (Storage->BrowserStorage->ReferenceCount > 1) { - ConfigRequestAdjust(Storage); - return; - } + if (Storage->BrowserStorage->Type == EFI_HII_VARSTORE_EFI_VARIABLE) { + return EFI_SUCCESS; + } + if (Storage->BrowserStorage->Type == EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER) { + Status = EFI_SUCCESS; + // + // EFI varstore data all get from variable, so no need to get again. + // + if (Storage->BrowserStorage->ReferenceCount == 1) { Status = gRT->GetVariable ( Storage->BrowserStorage->Name, &Storage->BrowserStorage->Guid, @@ -4235,78 +3791,55 @@ LoadStorage ( (UINTN*)&Storage->BrowserStorage->Size, Storage->BrowserStorage->EditBuffer ); - // - // If get variable fail, extract default from IFR binary - // - if (EFI_ERROR (Status)) { - ExtractDefault (FormSet, NULL, EFI_HII_DEFAULT_CLASS_STANDARD, FormSetLevel, GetDefaultForStorage, Storage->BrowserStorage, TRUE); - } - - Storage->BrowserStorage->ConfigRequest = AllocateCopyPool (StrSize (Storage->ConfigRequest), Storage->ConfigRequest); - // - // Input NULL for ConfigRequest field means sync all fields from editbuffer to buffer. - // - SynchronizeStorage(FormSet, Storage->BrowserStorage, NULL, TRUE); - break; + } + return Status; + } - case EFI_HII_VARSTORE_BUFFER: - case EFI_HII_VARSTORE_NAME_VALUE: - // - // Skip if there is no RequestElement - // - if (Storage->ElementCount == 0) { - return; - } + if (FormSet->ConfigAccess == NULL) { + return EFI_NOT_FOUND; + } - // - // Adjust the ConfigRequest string, only the field not saved in BrowserStorage->AllConfig - // will used to call ExtractConfig. - // If not elements need to udpate, return. - // - if (!ConfigRequestAdjust(Storage)) { - return; - } - ASSERT (Storage->ConfigElements != NULL); + if (Storage->ElementCount == 0) { + // + // Skip if there is no RequestElement + // + return EFI_SUCCESS; + } - Status = EFI_NOT_FOUND; - if (FormSet->ConfigAccess != NULL) { - // - // Request current settings from Configuration Driver - // - Status = FormSet->ConfigAccess->ExtractConfig ( - FormSet->ConfigAccess, - Storage->ConfigElements, - &Progress, - &Result - ); - - if (!EFI_ERROR (Status)) { - // - // Convert Result from to - // - StrPtr = StrStr (Result, L"&GUID="); - if (StrPtr != NULL) { - *StrPtr = L'\0'; - } - - Status = ConfigRespToStorage (Storage->BrowserStorage, Result); - FreePool (Result); - } - } + // + // Adjust the ConfigRequest string, only the field not saved in BrowserStorage->AllConfig + // will used to call ExtractConfig. + // + if (!ConfigRequestAdjust(Storage, &ConfigRequest)) { + return EFI_SUCCESS; + } - if (EFI_ERROR (Status)) { - // - // Base on the configRequest string to get default value. - // - GetDefaultForFormset (FormSet, Storage->BrowserStorage, Storage->ConfigElements); - } + // + // Request current settings from Configuration Driver + // + Status = FormSet->ConfigAccess->ExtractConfig ( + FormSet->ConfigAccess, + ConfigRequest, + &Progress, + &Result + ); + FreePool (ConfigRequest); - SynchronizeStorage(FormSet, Storage->BrowserStorage, Storage->ConfigElements, TRUE); - break; + if (EFI_ERROR (Status)) { + return Status; + } - default: - break; + // + // Convert Result from to + // + StrPtr = StrStr (Result, L"&GUID="); + if (StrPtr != NULL) { + *StrPtr = L'\0'; } + + Status = ConfigRespToStorage (Storage->BrowserStorage, Result); + FreePool (Result); + return Status; } /** @@ -4314,15 +3847,22 @@ LoadStorage ( @param FormSet FormSet data structure. + @retval EFI_SUCCESS The function completed successfully. + **/ -VOID +EFI_STATUS InitializeCurrentSetting ( IN OUT FORM_BROWSER_FORMSET *FormSet ) { LIST_ENTRY *Link; + LIST_ENTRY *Link2; FORMSET_STORAGE *Storage; - FORM_BROWSER_FORMSET *OldFormSet; + FORMSET_STORAGE *StorageSrc; + FORMSET_STORAGE *OldStorage; + FORM_BROWSER_FORM *Form; + FORM_BROWSER_FORM *Form2; + EFI_STATUS Status; // // Extract default from IFR binary for no storage questions. @@ -4336,21 +3876,77 @@ InitializeCurrentSetting ( while (!IsNull (&FormSet->StorageListHead, Link)) { Storage = FORMSET_STORAGE_FROM_LINK (Link); - LoadStorage (FormSet, Storage); + OldStorage = NULL; + if (gOldFormSet != NULL) { + // + // Try to find the Storage in backup formset gOldFormSet + // + Link2 = GetFirstNode (&gOldFormSet->StorageListHead); + while (!IsNull (&gOldFormSet->StorageListHead, Link2)) { + StorageSrc = FORMSET_STORAGE_FROM_LINK (Link2); + + if (StorageSrc->VarStoreId == Storage->VarStoreId) { + OldStorage = StorageSrc; + break; + } + + Link2 = GetNextNode (&gOldFormSet->StorageListHead, Link2); + } + } + + // + // Storage is not found in backup formset and current global storage not has other driver used, + // request it from ConfigDriver + // + if (OldStorage == NULL) { + Status = LoadStorage (FormSet, Storage); + + if (EFI_ERROR (Status)) { + // + // If get last time changed value failed, extract default from IFR binary + // + ExtractDefault (FormSet, NULL, EFI_HII_DEFAULT_CLASS_STANDARD, FormSetLevel, GetDefaultForStorage, Storage->BrowserStorage, TRUE); + // + // ExtractDefault will set the NV flag to TRUE, so need this function to clean the flag + // in current situation. + // + UpdateNvInfoInForm (FormSet, FALSE); + } + + // + // Now Edit Buffer is filled with default values(lower priority) or current + // settings(higher priority), sychronize it to shadow Buffer + // + SynchronizeStorage (Storage->BrowserStorage, TRUE); + } Link = GetNextNode (&FormSet->StorageListHead, Link); } // - // Try to find pre FormSet in the maintain backup list. - // If old formset != NULL, destroy this formset. Add new formset to gBrowserFormSetList. + // If has old formset, get the old nv update status. // - OldFormSet = GetFormSetFromHiiHandle (FormSet->HiiHandle); - if (OldFormSet != NULL) { - RemoveEntryList (&OldFormSet->Link); - DestroyFormSet (OldFormSet); + if (gOldFormSet != NULL) { + Link = GetFirstNode (&FormSet->FormListHead); + while (!IsNull (&FormSet->FormListHead, Link)) { + Form = FORM_BROWSER_FORM_FROM_LINK (Link); + + Link2 = GetFirstNode (&gOldFormSet->FormListHead); + while (!IsNull (&gOldFormSet->FormListHead, Link2)) { + Form2 = FORM_BROWSER_FORM_FROM_LINK (Link2); + + if (Form->FormId == Form2->FormId) { + Form->NvUpdateRequired = Form2->NvUpdateRequired; + break; + } + + Link2 = GetNextNode (&gOldFormSet->FormListHead, Link2); + } + Link = GetNextNode (&FormSet->FormListHead, Link); + } } - InsertTailList (&gBrowserFormSetList, &FormSet->Link); + + return EFI_SUCCESS; } @@ -4533,6 +4129,7 @@ GetIfrBinaryData ( found in package list. On output, GUID of the formset found(if not NULL). @param FormSet FormSet data structure. + @param UpdateGlobalVar Whether need to update the global variable. @retval EFI_SUCCESS The function completed successfully. @retval EFI_NOT_FOUND The specified FormSet could not be found. @@ -4542,11 +4139,13 @@ EFI_STATUS InitializeFormSet ( IN EFI_HII_HANDLE Handle, IN OUT EFI_GUID *FormSetGuid, - OUT FORM_BROWSER_FORMSET *FormSet + OUT FORM_BROWSER_FORMSET *FormSet, + IN BOOLEAN UpdateGlobalVar ) { EFI_STATUS Status; EFI_HANDLE DriverHandle; + UINT16 Index; Status = GetIfrBinaryData (Handle, FormSetGuid, &FormSet->IfrBinaryLength, &FormSet->IfrBinaryData); if (EFI_ERROR (Status)) { @@ -4556,7 +4155,6 @@ InitializeFormSet ( FormSet->Signature = FORM_BROWSER_FORMSET_SIGNATURE; FormSet->HiiHandle = Handle; CopyMem (&FormSet->Guid, FormSetGuid, sizeof (EFI_GUID)); - FormSet->QuestionInited = FALSE; // // Retrieve ConfigAccess Protocol associated with this HiiPackageList @@ -4583,8 +4181,55 @@ InitializeFormSet ( // Parse the IFR binary OpCodes // Status = ParseOpCodes (FormSet); + if (EFI_ERROR (Status)) { + return Status; + } - return Status; + // + // If not need to update the global variable, just return. + // + if (!UpdateGlobalVar) { + return Status; + } + + // + // Set VFR type by FormSet SubClass field + // + gClassOfVfr = FORMSET_CLASS_PLATFORM_SETUP; + if (FormSet->SubClass == EFI_FRONT_PAGE_SUBCLASS) { + gClassOfVfr = FORMSET_CLASS_FRONT_PAGE; + } + + // + // Set VFR type by FormSet class guid + // + for (Index = 0; Index < 3; Index ++) { + if (CompareGuid (&FormSet->ClassGuid[Index], &gEfiHiiPlatformSetupFormsetGuid)) { + gClassOfVfr |= FORMSET_CLASS_PLATFORM_SETUP; + break; + } + } + + gFunctionKeySetting = ENABLE_FUNCTION_KEY_SETTING; + + if ((gClassOfVfr & FORMSET_CLASS_FRONT_PAGE) == FORMSET_CLASS_FRONT_PAGE) { + gFrontPageHandle = FormSet->HiiHandle; + gFunctionKeySetting = NONE_FUNCTION_KEY_SETTING; + } + + // + // Match GUID to find out the function key setting. If match fail, use the default setting. + // + for (Index = 0; Index < sizeof (gFunctionKeySettingTable) / sizeof (FUNCTIION_KEY_SETTING); Index++) { + if (CompareGuid (&FormSet->Guid, &(gFunctionKeySettingTable[Index].FormSetGuid))) { + // + // Update the function key setting. + // + gFunctionKeySetting = gFunctionKeySettingTable[Index].KeySetting; + } + } + + return EFI_SUCCESS; } @@ -4600,7 +4245,6 @@ SaveBrowserContext ( ) { BROWSER_CONTEXT *Context; - FORM_ENTRY_INFO *MenuList; gBrowserContextCount++; if (gBrowserContextCount == 1) { @@ -4618,23 +4262,47 @@ SaveBrowserContext ( // // Save FormBrowser context // - Context->Selection = gCurrentSelection; + Context->BannerData = gBannerData; + Context->ClassOfVfr = gClassOfVfr; + Context->FunctionKeySetting = gFunctionKeySetting; Context->ResetRequired = gResetRequired; - Context->ExitRequired = gExitRequired; - Context->HiiHandle = mCurrentHiiHandle; - Context->FormId = mCurrentFormId; - CopyGuid (&Context->FormSetGuid, &mCurrentFormSetGuid); - - // - // Save the menu history data. - // - InitializeListHead(&Context->FormHistoryList); - while (!IsListEmpty (&mPrivateData.FormBrowserEx2.FormViewHistoryHead)) { - MenuList = FORM_ENTRY_INFO_FROM_LINK (mPrivateData.FormBrowserEx2.FormViewHistoryHead.ForwardLink); - RemoveEntryList (&MenuList->Link); - - InsertTailList(&Context->FormHistoryList, &MenuList->Link); - } + Context->Direction = gDirection; + Context->EnterString = gEnterString; + Context->EnterCommitString = gEnterCommitString; + Context->EnterEscapeString = gEnterEscapeString; + Context->EscapeString = gEscapeString; + Context->MoveHighlight = gMoveHighlight; + Context->MakeSelection = gMakeSelection; + Context->DecNumericInput = gDecNumericInput; + Context->HexNumericInput = gHexNumericInput; + Context->ToggleCheckBox = gToggleCheckBox; + Context->PromptForData = gPromptForData; + Context->PromptForPassword = gPromptForPassword; + Context->PromptForNewPassword = gPromptForNewPassword; + Context->ConfirmPassword = gConfirmPassword; + Context->ConfirmError = gConfirmError; + Context->PassowordInvalid = gPassowordInvalid; + Context->PressEnter = gPressEnter; + Context->EmptyString = gEmptyString; + Context->AreYouSure = gAreYouSure; + Context->YesResponse = gYesResponse; + Context->NoResponse = gNoResponse; + Context->MiniString = gMiniString; + Context->PlusString = gPlusString; + Context->MinusString = gMinusString; + Context->AdjustNumber = gAdjustNumber; + Context->SaveChanges = gSaveChanges; + Context->OptionMismatch = gOptionMismatch; + Context->FormSuppress = gFormSuppress; + Context->PromptBlockWidth = gPromptBlockWidth; + Context->OptionBlockWidth = gOptionBlockWidth; + Context->HelpBlockWidth = gHelpBlockWidth; + Context->OldFormSet = gOldFormSet; + Context->MenuRefreshHead = gMenuRefreshHead; + Context->ProtocolNotFound = gProtocolNotFound; + + CopyMem (&Context->ScreenDimensions, &gScreenDimensions, sizeof (gScreenDimensions)); + CopyMem (&Context->MenuOption, &gMenuOption, sizeof (gMenuOption)); // // Insert to FormBrowser context list @@ -4654,7 +4322,6 @@ RestoreBrowserContext ( { LIST_ENTRY *Link; BROWSER_CONTEXT *Context; - FORM_ENTRY_INFO *MenuList; ASSERT (gBrowserContextCount != 0); gBrowserContextCount--; @@ -4673,22 +4340,47 @@ RestoreBrowserContext ( // // Restore FormBrowser context // - gCurrentSelection = Context->Selection; + gBannerData = Context->BannerData; + gClassOfVfr = Context->ClassOfVfr; + gFunctionKeySetting = Context->FunctionKeySetting; gResetRequired = Context->ResetRequired; - gExitRequired = Context->ExitRequired; - mCurrentHiiHandle = Context->HiiHandle; - mCurrentFormId = Context->FormId; - CopyGuid (&mCurrentFormSetGuid, &Context->FormSetGuid); - - // - // Restore the menu history data. - // - while (!IsListEmpty (&Context->FormHistoryList)) { - MenuList = FORM_ENTRY_INFO_FROM_LINK (Context->FormHistoryList.ForwardLink); - RemoveEntryList (&MenuList->Link); - - InsertTailList(&mPrivateData.FormBrowserEx2.FormViewHistoryHead, &MenuList->Link); - } + gDirection = Context->Direction; + gEnterString = Context->EnterString; + gEnterCommitString = Context->EnterCommitString; + gEnterEscapeString = Context->EnterEscapeString; + gEscapeString = Context->EscapeString; + gMoveHighlight = Context->MoveHighlight; + gMakeSelection = Context->MakeSelection; + gDecNumericInput = Context->DecNumericInput; + gHexNumericInput = Context->HexNumericInput; + gToggleCheckBox = Context->ToggleCheckBox; + gPromptForData = Context->PromptForData; + gPromptForPassword = Context->PromptForPassword; + gPromptForNewPassword = Context->PromptForNewPassword; + gConfirmPassword = Context->ConfirmPassword; + gConfirmError = Context->ConfirmError; + gPassowordInvalid = Context->PassowordInvalid; + gPressEnter = Context->PressEnter; + gEmptyString = Context->EmptyString; + gAreYouSure = Context->AreYouSure; + gYesResponse = Context->YesResponse; + gNoResponse = Context->NoResponse; + gMiniString = Context->MiniString; + gPlusString = Context->PlusString; + gMinusString = Context->MinusString; + gAdjustNumber = Context->AdjustNumber; + gSaveChanges = Context->SaveChanges; + gOptionMismatch = Context->OptionMismatch; + gFormSuppress = Context->FormSuppress; + gPromptBlockWidth = Context->PromptBlockWidth; + gOptionBlockWidth = Context->OptionBlockWidth; + gHelpBlockWidth = Context->HelpBlockWidth; + gOldFormSet = Context->OldFormSet; + gMenuRefreshHead = Context->MenuRefreshHead; + gProtocolNotFound = Context->ProtocolNotFound; + + CopyMem (&gScreenDimensions, &Context->ScreenDimensions, sizeof (gScreenDimensions)); + CopyMem (&gMenuOption, &Context->MenuOption, sizeof (gMenuOption)); // // Remove from FormBrowser context list @@ -4748,7 +4440,7 @@ IsHiiHandleInBrowserContext ( // // HiiHandle is Current FormSet. // - if (mCurrentHiiHandle == Handle) { + if ((gOldFormSet != NULL) && (gOldFormSet->HiiHandle == Handle)) { return TRUE; } @@ -4758,7 +4450,7 @@ IsHiiHandleInBrowserContext ( Link = GetFirstNode (&gBrowserContextList); while (!IsNull (&gBrowserContextList, Link)) { Context = BROWSER_CONTEXT_FROM_LINK (Link); - if (Context->HiiHandle == Handle) { + if (Context->OldFormSet->HiiHandle == Handle) { // // HiiHandle is in BrowserContext // @@ -4770,83 +4462,6 @@ IsHiiHandleInBrowserContext ( return FALSE; } -/** - Perform Password check. - Passwork may be encrypted by driver that requires the specific check. - - @param Form Form where Password Statement is in. - @param Statement Password statement - @param PasswordString Password string to be checked. It may be NULL. - NULL means to restore password. - "" string can be used to checked whether old password does exist. - - @return Status Status of Password check. -**/ -EFI_STATUS -EFIAPI -PasswordCheck ( - IN FORM_DISPLAY_ENGINE_FORM *Form, - IN FORM_DISPLAY_ENGINE_STATEMENT *Statement, - IN EFI_STRING PasswordString OPTIONAL - ) -{ - EFI_STATUS Status; - EFI_HII_CONFIG_ACCESS_PROTOCOL *ConfigAccess; - EFI_BROWSER_ACTION_REQUEST ActionRequest; - EFI_IFR_TYPE_VALUE IfrTypeValue; - FORM_BROWSER_STATEMENT *Question; - - ConfigAccess = gCurrentSelection->FormSet->ConfigAccess; - Question = GetBrowserStatement(Statement); - ASSERT (Question != NULL); - - if ((Question->QuestionFlags & EFI_IFR_FLAG_CALLBACK) == EFI_IFR_FLAG_CALLBACK) { - if (ConfigAccess == NULL) { - return EFI_UNSUPPORTED; - } - } else { - if (PasswordString == NULL) { - return EFI_SUCCESS; - } - - if (StrnCmp (PasswordString, (CHAR16 *) Question->BufferValue, Question->StorageWidth/sizeof (CHAR16)) == 0) { - return EFI_SUCCESS; - } else { - return EFI_NOT_READY; - } - } - - // - // Prepare password string in HII database - // - if (PasswordString != NULL) { - IfrTypeValue.string = NewString (PasswordString, gCurrentSelection->FormSet->HiiHandle); - } else { - IfrTypeValue.string = 0; - } - - // - // Send password to Configuration Driver for validation - // - Status = ConfigAccess->Callback ( - ConfigAccess, - EFI_BROWSER_ACTION_CHANGING, - Question->QuestionId, - Question->HiiValue.Type, - &IfrTypeValue, - &ActionRequest - ); - - // - // Remove password string from HII database - // - if (PasswordString != NULL) { - DeleteString (IfrTypeValue.string, gCurrentSelection->FormSet->HiiHandle); - } - - return Status; -} - /** Find the registered HotKey based on KeyData. @@ -4897,7 +4512,7 @@ SetScope ( if (Scope >= MaxLevel) { return EFI_INVALID_PARAMETER; } - + // // When no hot key registered in system or on the first setting, // Scope can be set. @@ -5021,128 +4636,6 @@ RegiserExitHandler ( return; } -/** - Check whether the browser data has been modified. - - @retval TRUE Browser data is modified. - @retval FALSE No browser data is modified. - -**/ -BOOLEAN -EFIAPI -IsBrowserDataModified ( - VOID - ) -{ - LIST_ENTRY *Link; - FORM_BROWSER_FORMSET *FormSet; - - if (gCurrentSelection == NULL) { - return FALSE; - } - - switch (gBrowserSettingScope) { - case FormLevel: - return IsNvUpdateRequiredForForm (gCurrentSelection->Form); - - case FormSetLevel: - return IsNvUpdateRequiredForFormSet (gCurrentSelection->FormSet); - - case SystemLevel: - Link = GetFirstNode (&gBrowserFormSetList); - while (!IsNull (&gBrowserFormSetList, Link)) { - FormSet = FORM_BROWSER_FORMSET_FROM_LINK (Link); - if (IsNvUpdateRequiredForFormSet (FormSet)) { - return TRUE; - } - Link = GetNextNode (&gBrowserFormSetList, Link); - } - return FALSE; - - default: - return FALSE; - } -} - -/** - Execute the action requested by the Action parameter. - - @param[in] Action Execute the request action. - @param[in] DefaultId The default Id info when need to load default value. Only used when Action is BROWSER_ACTION_DEFAULT. - - @retval EFI_SUCCESS Execute the request action succss. - @retval EFI_INVALID_PARAMETER The input action value is invalid. - -**/ -EFI_STATUS -EFIAPI -ExecuteAction ( - IN UINT32 Action, - IN UINT16 DefaultId - ) -{ - EFI_STATUS Status; - - if (gCurrentSelection == NULL) { - return EFI_NOT_READY; - } - - Status = EFI_SUCCESS; - - // - // Executet the discard action. - // - if ((Action & BROWSER_ACTION_DISCARD) != 0) { - Status = DiscardForm (gCurrentSelection->FormSet, gCurrentSelection->Form, gBrowserSettingScope); - if (EFI_ERROR (Status)) { - return Status; - } - } - - // - // Executet the difault action. - // - if ((Action & BROWSER_ACTION_DEFAULT) != 0) { - Status = ExtractDefault (gCurrentSelection->FormSet, gCurrentSelection->Form, DefaultId, gBrowserSettingScope, GetDefaultForAll, NULL, FALSE); - if (EFI_ERROR (Status)) { - return Status; - } - } - - // - // Executet the submit action. - // - if ((Action & BROWSER_ACTION_SUBMIT) != 0) { - Status = SubmitForm (gCurrentSelection->FormSet, gCurrentSelection->Form, gBrowserSettingScope); - if (EFI_ERROR (Status)) { - return Status; - } - } - - // - // Executet the reset action. - // - if ((Action & BROWSER_ACTION_RESET) != 0) { - gResetRequired = TRUE; - } - - // - // Executet the exit action. - // - if ((Action & BROWSER_ACTION_EXIT) != 0) { - DiscardForm (gCurrentSelection->FormSet, gCurrentSelection->Form, gBrowserSettingScope); - if (gBrowserSettingScope == SystemLevel) { - if (ExitHandlerFunction != NULL) { - ExitHandlerFunction (); - } - } - - gExitRequired = TRUE; - } - - return Status; -} - /** Create reminder to let user to choose save or discard the changed browser data. Caller can use it to actively check the changed browser data. @@ -5162,6 +4655,12 @@ SaveReminder ( FORM_BROWSER_FORMSET *FormSet; BOOLEAN IsDataChanged; UINT32 DataSavedAction; + CHAR16 *YesResponse; + CHAR16 *NoResponse; + CHAR16 *EmptyString; + CHAR16 *ChangeReminderString; + CHAR16 *SaveConfirmString; + EFI_INPUT_KEY Key; DataSavedAction = BROWSER_NO_CHANGES; IsDataChanged = FALSE; @@ -5172,7 +4671,7 @@ SaveReminder ( if (!ValidateFormSet(FormSet)) { continue; } - if (IsNvUpdateRequiredForFormSet (FormSet)) { + if (IsNvUpdateRequired (FormSet)) { IsDataChanged = TRUE; break; } @@ -5186,19 +4685,42 @@ SaveReminder ( } // - // If data is changed, prompt user to save or discard it. + // If data is changed, prompt user // + gST->ConIn->ReadKeyStroke (gST->ConIn, &Key); + + YesResponse = GetToken (STRING_TOKEN (ARE_YOU_SURE_YES), gHiiHandle); + ASSERT (YesResponse != NULL); + NoResponse = GetToken (STRING_TOKEN (ARE_YOU_SURE_NO), gHiiHandle); + ASSERT (NoResponse != NULL); + EmptyString = GetToken (STRING_TOKEN (EMPTY_STRING), gHiiHandle); + ChangeReminderString = GetToken (STRING_TOKEN (CHANGE_REMINDER), gHiiHandle); + SaveConfirmString = GetToken (STRING_TOKEN (SAVE_CONFIRM), gHiiHandle); + do { - DataSavedAction = (UINT32) mFormDisplay->ConfirmDataChange(); + CreateDialog (4, TRUE, 0, NULL, &Key, EmptyString, ChangeReminderString, SaveConfirmString, EmptyString); + } while + (((Key.UnicodeChar | UPPER_LOWER_CASE_OFFSET) != (NoResponse[0] | UPPER_LOWER_CASE_OFFSET)) && + ((Key.UnicodeChar | UPPER_LOWER_CASE_OFFSET) != (YesResponse[0] | UPPER_LOWER_CASE_OFFSET)) + ); - if (DataSavedAction == BROWSER_SAVE_CHANGES) { - SubmitForm (NULL, NULL, SystemLevel); - break; - } else if (DataSavedAction == BROWSER_DISCARD_CHANGES) { - DiscardForm (NULL, NULL, SystemLevel); - break; - } - } while (1); + // + // If the user hits the YesResponse key + // + if ((Key.UnicodeChar | UPPER_LOWER_CASE_OFFSET) == (YesResponse[0] | UPPER_LOWER_CASE_OFFSET)) { + SubmitForm (NULL, NULL, SystemLevel); + DataSavedAction = BROWSER_SAVE_CHANGES; + } else { + DiscardForm (NULL, NULL, SystemLevel); + DataSavedAction = BROWSER_DISCARD_CHANGES; + gResetRequired = FALSE; + } + + FreePool (YesResponse); + FreePool (NoResponse); + FreePool (EmptyString); + FreePool (SaveConfirmString); + FreePool (ChangeReminderString); return DataSavedAction; } diff --git a/MdeModulePkg/Universal/SetupBrowserDxe/Setup.h b/MdeModulePkg/Universal/SetupBrowserDxe/Setup.h index 030cf32eac..9a0c739094 100644 --- a/MdeModulePkg/Universal/SetupBrowserDxe/Setup.h +++ b/MdeModulePkg/Universal/SetupBrowserDxe/Setup.h @@ -22,8 +22,7 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. #include #include #include -#include -#include +#include #include #include #include @@ -48,28 +47,105 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. #include #include #include -#include +#include "Colors.h" // // This is the generated header file which includes whatever needs to be exported (strings + IFR) // -#define UI_ACTION_NONE 0 -#define UI_ACTION_REFRESH_FORM 1 -#define UI_ACTION_REFRESH_FORMSET 2 -#define UI_ACTION_EXIT 3 +extern UINT8 SetupBrowserStrings[]; // +// Screen definitions +// +#define BANNER_HEIGHT 6 +#define BANNER_COLUMNS 3 +#define BANNER_LEFT_COLUMN_INDENT 1 + +#define FRONT_PAGE_HEADER_HEIGHT 6 +#define NONE_FRONT_PAGE_HEADER_HEIGHT 3 +#define LEFT_SKIPPED_COLUMNS 3 +#define FOOTER_HEIGHT 4 +#define STATUS_BAR_HEIGHT 1 +#define SCROLL_ARROW_HEIGHT 1 +#define POPUP_PAD_SPACE_COUNT 5 +#define POPUP_FRAME_WIDTH 2 + +// +// Definition for function key setting +// +#define NONE_FUNCTION_KEY_SETTING 0 +#define ENABLE_FUNCTION_KEY_SETTING 1 + +typedef struct { + EFI_GUID FormSetGuid; + UINTN KeySetting; +} FUNCTIION_KEY_SETTING; + +// +// Character definitions +// +#define CHAR_SPACE 0x0020 +#define UPPER_LOWER_CASE_OFFSET 0x20 + // // Time definitions // #define ONE_SECOND 10000000 +// +// Display definitions +// +#define LEFT_HYPER_DELIMITER L'<' +#define RIGHT_HYPER_DELIMITER L'>' + +#define LEFT_ONEOF_DELIMITER L'<' +#define RIGHT_ONEOF_DELIMITER L'>' + +#define LEFT_NUMERIC_DELIMITER L'[' +#define RIGHT_NUMERIC_DELIMITER L']' + +#define LEFT_CHECKBOX_DELIMITER L'[' +#define RIGHT_CHECKBOX_DELIMITER L']' + +#define CHECK_ON L'X' +#define CHECK_OFF L' ' + +#define TIME_SEPARATOR L':' +#define DATE_SEPARATOR L'/' + +#define YES_ANSWER L'Y' +#define NO_ANSWER L'N' + +// +// This is the Input Error Message +// +#define INPUT_ERROR 1 + +// +// This is the NV RAM update required Message +// +#define NV_UPDATE_REQUIRED 2 + +// +// Refresh the Status Bar with flags +// +#define REFRESH_STATUS_BAR 0xff + +// // Incremental string lenght of ConfigRequest // #define CONFIG_REQUEST_STRING_INCREMENTAL 1024 +// +// HII value compare result +// +#define HII_VALUE_UNDEFINED 0 +#define HII_VALUE_EQUAL 1 +#define HII_VALUE_LESS_THAN 2 +#define HII_VALUE_GREATER_THAN 3 + // // Incremental size of stack for expression // @@ -87,13 +163,16 @@ typedef struct { // // Produced protocol // - EFI_FORM_BROWSER2_PROTOCOL FormBrowser2; - EFI_FORM_BROWSER_EXTENSION_PROTOCOL FormBrowserEx; - - EDKII_FORM_BROWSER_EXTENSION2_PROTOCOL FormBrowserEx2; + EFI_FORM_BROWSER2_PROTOCOL FormBrowser2; + + EFI_FORM_BROWSER_EXTENSION_PROTOCOL FormBrowserEx; } SETUP_DRIVER_PRIVATE_DATA; +typedef struct { + EFI_STRING_ID Banner[BANNER_HEIGHT][BANNER_COLUMNS]; +} BANNER_DATA; + // // IFR relative definition // @@ -115,6 +194,16 @@ typedef struct { #define FORM_INCONSISTENT_VALIDATION 0 #define FORM_NO_SUBMIT_VALIDATION 1 +#define FORMSET_CLASS_PLATFORM_SETUP 0x0001 +#define FORMSET_CLASS_FRONT_PAGE 0x0002 + +typedef struct { + UINT8 Type; + UINT8 *Buffer; + UINT16 BufferLen; + EFI_IFR_TYPE_VALUE Value; +} EFI_HII_VALUE; + #define NAME_VALUE_NODE_SIGNATURE SIGNATURE_32 ('N', 'V', 'S', 'T') typedef struct { @@ -166,7 +255,6 @@ typedef struct { BROWSER_STORAGE *BrowserStorage; CHAR16 *ConfigRequest; // = + - CHAR16 *ConfigElements;// Elements need to load initial data. UINTN ElementCount; // Number of in the UINTN SpareStrLen; // Spare length of ConfigRequest string buffer } FORMSET_STORAGE; @@ -256,8 +344,6 @@ typedef struct { typedef struct { UINTN Signature; LIST_ENTRY Link; - - EFI_IFR_ONE_OF_OPTION *OpCode; // OneOfOption Data EFI_STRING_ID Text; UINT8 Flags; @@ -290,7 +376,6 @@ typedef struct { LIST_ENTRY Link; UINT8 Operand; // The operand (first byte) of this Statement or Question - EFI_IFR_OP_HEADER *OpCode; // // Statement Header @@ -299,11 +384,6 @@ typedef struct { EFI_STRING_ID Help; EFI_STRING_ID TextTwo; // For EFI_IFR_TEXT - // - // Fake Question Id, used for statement not has true QuestionId. - // - EFI_QUESTION_ID FakeQuestionId; - // // Question Header // @@ -337,7 +417,6 @@ typedef struct { EFI_DEFAULT_ID DefaultId; // for EFI_IFR_RESET_BUTTON EFI_GUID RefreshGuid; // for EFI_IFR_REFRESH_ID BOOLEAN Locked; // Whether this statement is locked. - BOOLEAN ValueChanged; // Whether this statement's value is changed. // // Get from IFR parsing // @@ -388,6 +467,8 @@ typedef struct { BOOLEAN ModalForm; // Whether this is a modal form. BOOLEAN Locked; // Whether this form is locked. + BOOLEAN NvUpdateRequired; // Whether this form has NV update request. + LIST_ENTRY ExpressionListHead; // List of Expressions (FORM_EXPRESSION) LIST_ENTRY StatementListHead; // List of Statements and Questions (FORM_BROWSER_STATEMENT) LIST_ENTRY ConfigRequestHead; // List of configreques for all storage. @@ -421,7 +502,6 @@ typedef struct { UINTN IfrBinaryLength; UINT8 *IfrBinaryData; - BOOLEAN QuestionInited; // Have finished question initilization? EFI_GUID Guid; EFI_STRING_ID FormSetTitle; EFI_STRING_ID Help; @@ -434,82 +514,84 @@ typedef struct { FORM_BROWSER_STATEMENT *StatementBuffer; // Buffer for all Statements and Questions EXPRESSION_OPCODE *ExpressionBuffer; // Buffer for all Expression OpCode - LIST_ENTRY StatementListOSF; // Statement list out side of the form. LIST_ENTRY StorageListHead; // Storage list (FORMSET_STORAGE) LIST_ENTRY DefaultStoreListHead; // DefaultStore list (FORMSET_DEFAULTSTORE) LIST_ENTRY FormListHead; // Form list (FORM_BROWSER_FORM) LIST_ENTRY ExpressionListHead; // List of Expressions (FORM_EXPRESSION) } FORM_BROWSER_FORMSET; -#define FORM_BROWSER_FORMSET_FROM_LINK(a) CR (a, FORM_BROWSER_FORMSET, Link, FORM_BROWSER_FORMSET_SIGNATURE) - -typedef struct { - LIST_ENTRY Link; - EFI_EVENT RefreshEvent; -} FORM_BROWSER_REFRESH_EVENT_NODE; -#define FORM_BROWSER_REFRESH_EVENT_FROM_LINK(a) BASE_CR (a, FORM_BROWSER_REFRESH_EVENT_NODE, Link) +#define FORM_BROWSER_FORMSET_FROM_LINK(a) CR (a, FORM_BROWSER_FORMSET, Link, FORM_BROWSER_FORMSET_SIGNATURE) +#define BROWSER_CONTEXT_SIGNATURE SIGNATURE_32 ('B', 'C', 'T', 'X') typedef struct { - EFI_HII_HANDLE Handle; - - // - // Target formset/form/Question information - // - EFI_GUID FormSetGuid; - UINT16 FormId; - UINT16 QuestionId; - UINTN Sequence; // used for time/date only. - - UINTN TopRow; - UINTN BottomRow; - UINTN PromptCol; - UINTN OptionCol; - UINTN CurrentRow; - - // - // Ation for Browser to taken: - // UI_ACTION_NONE - navigation inside a form - // UI_ACTION_REFRESH_FORM - re-evaluate expressions and repaint form - // UI_ACTION_REFRESH_FORMSET - re-parse formset IFR binary - // - UINTN Action; + UINTN Signature; + LIST_ENTRY Link; // - // Current selected fomset/form/Question + // Globals defined in Setup.c // - FORM_BROWSER_FORMSET *FormSet; - FORM_BROWSER_FORM *Form; - FORM_BROWSER_STATEMENT *Statement; + BANNER_DATA *BannerData; + UINTN ClassOfVfr; + UINTN FunctionKeySetting; + BOOLEAN ResetRequired; + UINT16 Direction; + EFI_SCREEN_DESCRIPTOR ScreenDimensions; + CHAR16 *EnterString; + CHAR16 *EnterCommitString; + CHAR16 *EnterEscapeString; + CHAR16 *EscapeString; + CHAR16 *MoveHighlight; + CHAR16 *MakeSelection; + CHAR16 *DecNumericInput; + CHAR16 *HexNumericInput; + CHAR16 *ToggleCheckBox; + CHAR16 *PromptForData; + CHAR16 *PromptForPassword; + CHAR16 *PromptForNewPassword; + CHAR16 *ConfirmPassword; + CHAR16 *ConfirmError; + CHAR16 *PassowordInvalid; + CHAR16 *PressEnter; + CHAR16 *EmptyString; + CHAR16 *AreYouSure; + CHAR16 *YesResponse; + CHAR16 *NoResponse; + CHAR16 *MiniString; + CHAR16 *PlusString; + CHAR16 *MinusString; + CHAR16 *AdjustNumber; + CHAR16 *SaveChanges; + CHAR16 *OptionMismatch; + CHAR16 *FormSuppress; + CHAR16 *ProtocolNotFound; + CHAR16 PromptBlockWidth; + CHAR16 OptionBlockWidth; + CHAR16 HelpBlockWidth; + FORM_BROWSER_FORMSET *OldFormSet; // - // Whether the Form is editable + // Globals defined in Ui.c // - BOOLEAN FormEditable; + LIST_ENTRY MenuOption; + VOID *MenuRefreshHead; +} BROWSER_CONTEXT; - FORM_ENTRY_INFO *CurrentMenu; -} UI_MENU_SELECTION; +#define BROWSER_CONTEXT_FROM_LINK(a) CR (a, BROWSER_CONTEXT, Link, BROWSER_CONTEXT_SIGNATURE) -#define BROWSER_CONTEXT_SIGNATURE SIGNATURE_32 ('B', 'C', 'T', 'X') +#define BROWSER_HOT_KEY_SIGNATURE SIGNATURE_32 ('B', 'H', 'K', 'S') typedef struct { UINTN Signature; LIST_ENTRY Link; + + EFI_INPUT_KEY *KeyData; + IN UINT32 Action; + IN UINT16 DefaultId; + IN EFI_STRING HelpString; +} BROWSER_HOT_KEY; - // - // Globals defined in Setup.c - // - BOOLEAN ResetRequired; - BOOLEAN ExitRequired; - EFI_HII_HANDLE HiiHandle; - EFI_GUID FormSetGuid; - EFI_FORM_ID FormId; - UI_MENU_SELECTION *Selection; - - LIST_ENTRY FormHistoryList; -} BROWSER_CONTEXT; - -#define BROWSER_CONTEXT_FROM_LINK(a) CR (a, BROWSER_CONTEXT, Link, BROWSER_CONTEXT_SIGNATURE) +#define BROWSER_HOT_KEY_FROM_LINK(a) CR (a, BROWSER_HOT_KEY, Link, BROWSER_HOT_KEY_SIGNATURE) // // Scope for get defaut value. It may be GetDefaultForNoStorage, GetDefaultForStorage or GetDefaultForAll. @@ -532,31 +614,72 @@ typedef enum { } GET_SET_QUESTION_VALUE_WITH; extern EFI_HII_DATABASE_PROTOCOL *mHiiDatabase; +extern EFI_HII_STRING_PROTOCOL *mHiiString; extern EFI_HII_CONFIG_ROUTING_PROTOCOL *mHiiConfigRouting; extern EFI_DEVICE_PATH_FROM_TEXT_PROTOCOL *mPathFromText; -extern EDKII_FORM_DISPLAY_ENGINE_PROTOCOL *mFormDisplay; +extern BANNER_DATA *gBannerData; +extern EFI_HII_HANDLE gFrontPageHandle; +extern UINTN gClassOfVfr; +extern UINTN gFunctionKeySetting; extern BOOLEAN gResetRequired; -extern BOOLEAN gExitRequired; +extern EFI_HII_HANDLE gHiiHandle; +extern UINT16 gDirection; +extern EFI_SCREEN_DESCRIPTOR gScreenDimensions; +extern FORM_BROWSER_FORMSET *gOldFormSet; extern LIST_ENTRY gBrowserFormSetList; extern LIST_ENTRY gBrowserHotKeyList; extern BROWSER_SETTING_SCOPE gBrowserSettingScope; extern EXIT_HANDLER ExitHandlerFunction; -extern EFI_HII_HANDLE mCurrentHiiHandle; +extern UINTN gFooterHeight; + // // Browser Global Strings // +extern CHAR16 *gDiscardFailed; +extern CHAR16 *gDefaultFailed; +extern CHAR16 *gEnterString; +extern CHAR16 *gEnterCommitString; +extern CHAR16 *gEnterEscapeString; +extern CHAR16 *gEscapeString; +extern CHAR16 *gSaveFailed; +extern CHAR16 *gMoveHighlight; +extern CHAR16 *gMakeSelection; +extern CHAR16 *gDecNumericInput; +extern CHAR16 *gHexNumericInput; +extern CHAR16 *gToggleCheckBox; +extern CHAR16 *gPromptForData; +extern CHAR16 *gPromptForPassword; +extern CHAR16 *gPromptForNewPassword; +extern CHAR16 *gConfirmPassword; +extern CHAR16 *gConfirmError; +extern CHAR16 *gPassowordInvalid; +extern CHAR16 *gPressEnter; extern CHAR16 *gEmptyString; +extern CHAR16 *gAreYouSure; +extern CHAR16 *gYesResponse; +extern CHAR16 *gNoResponse; +extern CHAR16 *gMiniString; +extern CHAR16 *gPlusString; +extern CHAR16 *gMinusString; +extern CHAR16 *gAdjustNumber; +extern CHAR16 *gSaveChanges; +extern CHAR16 *gOptionMismatch; +extern CHAR16 *gFormSuppress; +extern CHAR16 *gProtocolNotFound; + +extern CHAR16 gPromptBlockWidth; +extern CHAR16 gOptionBlockWidth; +extern CHAR16 gHelpBlockWidth; extern EFI_GUID gZeroGuid; +extern EFI_GUID gTianoHiiIfrGuid; -extern UI_MENU_SELECTION *gCurrentSelection; - +#include "Ui.h" // // Global Procedure Defines // -#include "Expression.h" /** Initialize the HII String Token to the correct values. @@ -567,6 +690,91 @@ InitializeBrowserStrings ( VOID ); +/** + Prints a unicode string to the default console, + using L"%s" format. + + @param String String pointer. + + @return Length of string printed to the console + +**/ +UINTN +PrintString ( + IN CHAR16 *String + ); + +/** + Prints a chracter to the default console, + using L"%c" format. + + @param Character Character to print. + + @return Length of string printed to the console. + +**/ +UINTN +PrintChar ( + CHAR16 Character + ); + +/** + Prints a formatted unicode string to the default console, at + the supplied cursor position. + + @param Column The cursor position to print the string at. + @param Row The cursor position to print the string at + @param Fmt Format string + @param ... Variable argument list for formating string. + + @return Length of string printed to the console + +**/ +UINTN +EFIAPI +PrintAt ( + IN UINTN Column, + IN UINTN Row, + IN CHAR16 *Fmt, + ... + ); + +/** + Prints a unicode string to the default console, at + the supplied cursor position, using L"%s" format. + + @param Column The cursor position to print the string at. + @param Row The cursor position to print the string at + @param String String pointer. + + @return Length of string printed to the console + +**/ +UINTN +PrintStringAt ( + IN UINTN Column, + IN UINTN Row, + IN CHAR16 *String + ); + +/** + Prints a chracter to the default console, at + the supplied cursor position, using L"%c" format. + + @param Column The cursor position to print the string at. + @param Row The cursor position to print the string at. + @param Character Character to print. + + @return Length of string printed to the console. + +**/ +UINTN +PrintCharAt ( + IN UINTN Column, + IN UINTN Row, + CHAR16 Character + ); + /** Parse opcodes in the formset IFR binary. @@ -592,6 +800,17 @@ DestroyFormSet ( IN OUT FORM_BROWSER_FORMSET *FormSet ); +/** + This function displays the page frame. + + @param Selection Selection contains the information about + the Selection, form and formset to be displayed. + Selection action may be updated in retrieve callback. +**/ +VOID +DisplayPageFrame ( + IN UI_MENU_SELECTION *Selection + ); /** Create a new string in HII Package List. @@ -640,6 +859,59 @@ GetToken ( IN EFI_HII_HANDLE HiiHandle ); +/** + Draw a pop up windows based on the dimension, number of lines and + strings specified. + + @param RequestedWidth The width of the pop-up. + @param NumberOfLines The number of lines. + @param Marker The variable argument list for the list of string to be printed. + +**/ +VOID +CreateSharedPopUp ( + IN UINTN RequestedWidth, + IN UINTN NumberOfLines, + IN VA_LIST Marker + ); + +/** + Routine used to abstract a generic dialog interface and return the selected key or string + + @param NumberOfLines The number of lines for the dialog box + @param HotKey Defines whether a single character is parsed + (TRUE) and returned in KeyValue or a string is + returned in StringBuffer. Two special characters + are considered when entering a string, a SCAN_ESC + and an CHAR_CARRIAGE_RETURN. SCAN_ESC terminates + string input and returns + @param MaximumStringSize The maximum size in bytes of a typed in string + (each character is a CHAR16) and the minimum + string returned is two bytes + @param StringBuffer The passed in pointer to the buffer which will + hold the typed in string if HotKey is FALSE + @param KeyValue The EFI_KEY value returned if HotKey is TRUE.. + @param ... A series of (quantity == NumberOfLines) text + strings which will be used to construct the dialog + box + + @retval EFI_SUCCESS Displayed dialog and received user interaction + @retval EFI_INVALID_PARAMETER One of the parameters was invalid (e.g. + (StringBuffer == NULL) && (HotKey == FALSE)) + @retval EFI_DEVICE_ERROR User typed in an ESC character to exit the routine + +**/ +EFI_STATUS +EFIAPI +CreateDialog ( + IN UINTN NumberOfLines, + IN BOOLEAN HotKey, + IN UINTN MaximumStringSize, + OUT CHAR16 *StringBuffer, + OUT EFI_INPUT_KEY *KeyValue, + ... + ); + /** Get Value for given Name from a NameValue Storage. @@ -667,7 +939,6 @@ GetValueByName ( @param Name The Name. @param Value The Value to set. @param SetValueTo Whether update editValue or Value. - @param ReturnNode The node use the input name. @retval EFI_SUCCESS Value found for given Name. @retval EFI_NOT_FOUND No such Name found in NameValue storage. @@ -675,31 +946,10 @@ GetValueByName ( **/ EFI_STATUS SetValueByName ( - IN BROWSER_STORAGE *Storage, - IN CHAR16 *Name, - IN CHAR16 *Value, - IN GET_SET_QUESTION_VALUE_WITH SetValueTo, - OUT NAME_VALUE_NODE **ReturnNode - ); - -/** - Validate whether this question's value has changed. - - @param FormSet FormSet data structure. - @param Form Form data structure. - @param Question Question to be initialized. - @param GetValueFrom Where to get value, may from editbuffer, buffer or hii driver. - - @retval TRUE Question's value has changed. - @retval FALSE Question's value has not changed - -**/ -BOOLEAN -IsQuestionValueChanged ( - IN FORM_BROWSER_FORMSET *FormSet, - IN FORM_BROWSER_FORM *Form, - IN OUT FORM_BROWSER_STATEMENT *Question, - IN GET_SET_QUESTION_VALUE_WITH GetValueFrom + IN BROWSER_STORAGE *Storage, + IN CHAR16 *Name, + IN CHAR16 *Value, + IN GET_SET_QUESTION_VALUE_WITH SetValueTo ); /** @@ -821,8 +1071,10 @@ GetQuestionDefault ( @param FormSet FormSet data structure. + @retval EFI_SUCCESS The function completed successfully. + **/ -VOID +EFI_STATUS InitializeCurrentSetting ( IN OUT FORM_BROWSER_FORMSET *FormSet ); @@ -835,6 +1087,7 @@ InitializeCurrentSetting ( GUID), take the first FormSet found in package list. @param FormSet FormSet data structure. + @param UpdateGlobalVar Whether need to update the global variable. @retval EFI_SUCCESS The function completed successfully. @retval EFI_NOT_FOUND The specified FormSet could not be found. @@ -844,7 +1097,8 @@ EFI_STATUS InitializeFormSet ( IN EFI_HII_HANDLE Handle, IN OUT EFI_GUID *FormSetGuid, - OUT FORM_BROWSER_FORMSET *FormSet + OUT FORM_BROWSER_FORMSET *FormSet, + IN BOOLEAN UpdateGlobalVar ); /** @@ -922,7 +1176,6 @@ LoadFormSetConfig ( @param Storage The Storage to be conveted. @param ConfigResp The returned . @param ConfigRequest The ConfigRequest string. - @param GetEditBuf Get the data from editbuffer or buffer. @retval EFI_SUCCESS Convert success. @retval EFI_INVALID_PARAMETER Incorrect storage type. @@ -932,8 +1185,7 @@ EFI_STATUS StorageToConfigResp ( IN BROWSER_STORAGE *Storage, IN CHAR16 **ConfigResp, - IN CHAR16 *ConfigRequest, - IN BOOLEAN GetEditBuf + IN CHAR16 *ConfigRequest ); /** @@ -958,8 +1210,10 @@ ConfigRespToStorage ( @param FormSet FormSet data structure. @param Storage Buffer Storage. + @retval EFI_SUCCESS The function completed successfully. + **/ -VOID +EFI_STATUS LoadStorage ( IN FORM_BROWSER_FORMSET *FormSet, IN FORMSET_STORAGE *Storage @@ -1095,29 +1349,30 @@ BrowserCallback ( about the Selection, form and formset to be displayed. On output, Selection return the screen item that is selected by user. - @param SettingLevel Input Settting level, if it is FormLevel, just exit current form. - else, we need to exit current formset. + @param Repaint Whether need to repaint the menu. + @param NewLine Whether need to show at new line. - @retval TRUE Exit current form. - @retval FALSE User press ESC and keep in current form. + @retval TRUE Need return. + @retval FALSE No need to return. **/ BOOLEAN FindNextMenu ( - IN OUT UI_MENU_SELECTION *Selection, - IN BROWSER_SETTING_SCOPE SettingLevel + IN OUT UI_MENU_SELECTION *Selection, + IN BOOLEAN *Repaint, + IN BOOLEAN *NewLine ); /** - check whether the form need to update the NV. + check whether the formset need to update the NV. - @param Form Form data structure. + @param FormSet FormSet data structure. + @param SetValue Whether set new value or clear old value. - @retval TRUE Need to update the NV. - @retval FALSE No need to update the NV. **/ -BOOLEAN -IsNvUpdateRequiredForForm ( - IN FORM_BROWSER_FORM *Form +VOID +UpdateNvInfoInForm ( + IN FORM_BROWSER_FORMSET *FormSet, + IN BOOLEAN SetValue ); /** @@ -1128,22 +1383,9 @@ IsNvUpdateRequiredForForm ( @retval TRUE Need to update the NV. @retval FALSE No need to update the NV. **/ -BOOLEAN -IsNvUpdateRequiredForFormSet ( - IN FORM_BROWSER_FORMSET *FormSet - ); - -/** - Check whether the storage data for current form set is changed. - - @param FormSet FormSet data structure. - - @retval TRUE Data is changed. - @retval FALSE Data is not changed. -**/ BOOLEAN -IsStorageDataChangedForFormSet ( - IN FORM_BROWSER_FORMSET *FormSet +IsNvUpdateRequired ( + IN FORM_BROWSER_FORMSET *FormSet ); /** @@ -1274,38 +1516,6 @@ RegiserExitHandler ( IN EXIT_HANDLER Handler ); -/** - - Check whether the browser data has been modified. - - @retval TRUE Browser data is changed. - @retval FALSE No browser data is changed. - -**/ -BOOLEAN -EFIAPI -IsBrowserDataModified ( - VOID - ); - -/** - - Execute the action requested by the Action parameter. - - @param[in] Action Execute the request action. - @param[in] DefaultId The default Id info when need to load default value. - - @retval EFI_SUCCESS Execute the request action succss. - @retval EFI_INVALID_PARAMETER The input action value is invalid. - -**/ -EFI_STATUS -EFIAPI -ExecuteAction ( - IN UINT32 Action, - IN UINT16 DefaultId - ); - /** Create reminder to let user to choose save or discard the changed browser data. Caller can use it to actively check the changed browser data. @@ -1334,267 +1544,6 @@ GetHotKeyFromRegisterList ( IN EFI_INPUT_KEY *KeyData ); -/** - - Get FORM_BROWSER_STATEMENT from FORM_DISPLAY_ENGINE_STATEMENT based on the OpCode info. - - @param DisplayStatement The input FORM_DISPLAY_ENGINE_STATEMENT. - - @retval FORM_BROWSER_STATEMENT The return FORM_BROWSER_STATEMENT info. - -**/ -FORM_BROWSER_STATEMENT * -GetBrowserStatement ( - IN FORM_DISPLAY_ENGINE_STATEMENT *DisplayStatement - ); - -/** - Password may be stored as encrypted by Configuration Driver. When change a - password, user will be challenged with old password. To validate user input old - password, we will send the clear text to Configuration Driver via Callback(). - Configuration driver is responsible to check the passed in password and return - the validation result. If validation pass, state machine in password Callback() - will transit from BROWSER_STATE_VALIDATE_PASSWORD to BROWSER_STATE_SET_PASSWORD. - After user type in new password twice, Callback() will be invoked to send the - new password to Configuration Driver. - - @param Selection Pointer to UI_MENU_SELECTION. - @param MenuOption The MenuOption for this password Question. - @param String The clear text of password. - - @retval EFI_NOT_AVAILABLE_YET Callback() request to terminate password input. - @return In state of BROWSER_STATE_VALIDATE_PASSWORD: - @retval EFI_SUCCESS Password correct, Browser will prompt for new - password. - @retval EFI_NOT_READY Password incorrect, Browser will show error - message. - @retval Other Browser will do nothing. - @return In state of BROWSER_STATE_SET_PASSWORD: - @retval EFI_SUCCESS Set password success. - @retval Other Set password failed. - -**/ -EFI_STATUS -PasswordCallback ( - IN UI_MENU_SELECTION *Selection, - IN FORM_BROWSER_STATEMENT *Question, - IN CHAR16 *String - ); - -/** - Display error message for invalid password. - -**/ -VOID -PasswordInvalid ( - VOID - ); - -/** - The worker function that send the displays to the screen. On output, - the selection made by user is returned. - - @param Selection On input, Selection tell setup browser the information - about the Selection, form and formset to be displayed. - On output, Selection return the screen item that is selected - by user. - - @retval EFI_SUCCESS The page is displayed successfully. - @return Other value if the page failed to be diplayed. - -**/ -EFI_STATUS -SetupBrowser ( - IN OUT UI_MENU_SELECTION *Selection - ); - -/** - Free up the resource allocated for all strings required - by Setup Browser. - -**/ -VOID -FreeBrowserStrings ( - VOID - ); - -/** - Create a menu with specified formset GUID and form ID, and add it as a child - of the given parent menu. - - @param HiiHandle Hii handle related to this formset. - @param FormSetGuid The Formset Guid of menu to be added. - @param FormId The Form ID of menu to be added. - @param QuestionId The question id of this menu to be added. - - @return A pointer to the newly added menu or NULL if memory is insufficient. - -**/ -FORM_ENTRY_INFO * -UiAddMenuList ( - IN EFI_HII_HANDLE HiiHandle, - IN EFI_GUID *FormSetGuid, - IN UINT16 FormId, - IN UINT16 QuestionId - ); - -/** - Search Menu with given FormSetGuid and FormId in all cached menu list. - - @param HiiHandle HiiHandle for FormSet. - @param FormSetGuid The Formset GUID of the menu to search. - @param FormId The Form ID of menu to search. - - @return A pointer to menu found or NULL if not found. - -**/ -FORM_ENTRY_INFO * -UiFindMenuList ( - IN EFI_HII_HANDLE HiiHandle, - IN EFI_GUID *FormSetGuid, - IN UINT16 FormId - ); - -/** - Free Menu list linked list. - - @param MenuListHead One Menu list point in the menu list. - -**/ -VOID -UiFreeMenuList ( - LIST_ENTRY *MenuListHead - ); - -/** - Find parent menu for current menu. - - @param CurrentMenu Current Menu - - @retval The parent menu for current menu. -**/ -FORM_ENTRY_INFO * -UiFindParentMenu ( - IN FORM_ENTRY_INFO *CurrentMenu - ); - -/** - Search an Option of a Question by its value. - - @param Question The Question - @param OptionValue Value for Option to be searched. - - @retval Pointer Pointer to the found Option. - @retval NULL Option not found. - -**/ -QUESTION_OPTION * -ValueToOption ( - IN FORM_BROWSER_STATEMENT *Question, - IN EFI_HII_VALUE *OptionValue - ); -/** - Return data element in an Array by its Index. - - @param Array The data array. - @param Type Type of the data in this array. - @param Index Zero based index for data in this array. - - @retval Value The data to be returned - -**/ -UINT64 -GetArrayData ( - IN VOID *Array, - IN UINT8 Type, - IN UINTN Index - ); - -/** - Set value of a data element in an Array by its Index. - - @param Array The data array. - @param Type Type of the data in this array. - @param Index Zero based index for data in this array. - @param Value The value to be set. - -**/ -VOID -SetArrayData ( - IN VOID *Array, - IN UINT8 Type, - IN UINTN Index, - IN UINT64 Value - ); - -/** - Compare two Hii value. - - @param Value1 Expression value to compare on left-hand. - @param Value2 Expression value to compare on right-hand. - @param Result Return value after compare. - retval 0 Two operators equal. - return Positive value if Value1 is greater than Value2. - retval Negative value if Value1 is less than Value2. - @param HiiHandle Only required for string compare. - - @retval other Could not perform compare on two values. - @retval EFI_SUCCESS Compare the value success. - -**/ -EFI_STATUS -CompareHiiValue ( - IN EFI_HII_VALUE *Value1, - IN EFI_HII_VALUE *Value2, - OUT INTN *Result, - IN EFI_HII_HANDLE HiiHandle OPTIONAL - ); - -/** - Perform Password check. - Passwork may be encrypted by driver that requires the specific check. - - @param Form Form where Password Statement is in. - @param Statement Password statement - @param PasswordString Password string to be checked. It may be NULL. - NULL means to restore password. - "" string can be used to checked whether old password does exist. - - @return Status Status of Password check. -**/ -EFI_STATUS -EFIAPI -PasswordCheck ( - IN FORM_DISPLAY_ENGINE_FORM *Form, - IN FORM_DISPLAY_ENGINE_STATEMENT *Statement, - IN EFI_STRING PasswordString OPTIONAL - ); - -/** - - Get FORM_BROWSER_STATEMENT from FORM_DISPLAY_ENGINE_STATEMENT based on the OpCode info. - - @param DisplayStatement The input FORM_DISPLAY_ENGINE_STATEMENT. - - @retval FORM_BROWSER_STATEMENT The return FORM_BROWSER_STATEMENT info. - -**/ -FORM_BROWSER_STATEMENT * -GetBrowserStatement ( - IN FORM_DISPLAY_ENGINE_STATEMENT *DisplayStatement - ); - -/** - - Initialize the Display form structure data. - -**/ -VOID -InitializeDisplayFormData ( - VOID - ); - - /** Base on the current formset info, clean the ConfigRequest string in browser storage. @@ -1605,5 +1554,5 @@ VOID CleanBrowserStorage ( IN OUT FORM_BROWSER_FORMSET *FormSet ); - + #endif diff --git a/MdeModulePkg/Universal/SetupBrowserDxe/SetupBrowserDxe.inf b/MdeModulePkg/Universal/SetupBrowserDxe/SetupBrowserDxe.inf index a3f3a6fc2c..7e740bc099 100644 --- a/MdeModulePkg/Universal/SetupBrowserDxe/SetupBrowserDxe.inf +++ b/MdeModulePkg/Universal/SetupBrowserDxe/SetupBrowserDxe.inf @@ -19,7 +19,7 @@ BASE_NAME = SetupBrowser FILE_GUID = EBf342FE-B1D3-4EF8-957C-8048606FF671 MODULE_TYPE = DXE_DRIVER - VERSION_STRING = 2.0 + VERSION_STRING = 1.0 ENTRY_POINT = InitializeSetup # @@ -29,12 +29,19 @@ # [Sources] + SetupBrowserStr.uni Setup.c Setup.h IfrParse.c Expression.c + InputHandler.c + Print.c Presentation.c - Expression.h + ProcessOptions.c + Ui.c + Ui.h + Colors.h + [Packages] MdePkg/MdePkg.dec @@ -52,27 +59,34 @@ HiiLib DevicePathLib PcdLib - UefiLib [Guids] + gEfiIfrTianoGuid ## CONSUMES ## GUID gEfiIfrFrameworkGuid ## CONSUMES ## GUID gEfiHiiPlatformSetupFormsetGuid gEfiHiiStandardFormGuid ## SOMETIMES_CONSUMES ## GUID [Protocols] gEfiHiiConfigAccessProtocolGuid ## CONSUMES + gEfiHiiStringProtocolGuid ## CONSUMES gEfiFormBrowser2ProtocolGuid ## PRODUCES - gEdkiiFormBrowserEx2ProtocolGuid ## PRODUCES + gEfiFormBrowserExProtocolGuid ## PRODUCES gEfiHiiConfigRoutingProtocolGuid ## CONSUMES gEfiHiiDatabaseProtocolGuid ## CONSUMES gEfiUnicodeCollation2ProtocolGuid ## CONSUMES gEfiUserManagerProtocolGuid ## SOMETIMES_CONSUMES gEfiDevicePathFromTextProtocolGuid ## SOMETIMES_CONSUMES - gEdkiiFormDisplayEngineProtocolGuid ## PRODUCE - gEfiFormBrowserExProtocolGuid ## PRODUCE [FeaturePcd] gEfiMdeModulePkgTokenSpaceGuid.PcdFrameworkCompatibilitySupport ## CONSUMES + gEfiMdeModulePkgTokenSpaceGuid.PcdBrowserGrayOutTextStatement ## CONSUMES + gEfiMdeModulePkgTokenSpaceGuid.PcdBrowerGrayOutReadOnlyMenu ## CONSUMES + +[Pcd] + gEfiMdeModulePkgTokenSpaceGuid.PcdBrowserSubtitleTextColor ## CONSUMES + gEfiMdeModulePkgTokenSpaceGuid.PcdBrowserFieldTextColor ## CONSUMES + gEfiMdeModulePkgTokenSpaceGuid.PcdBrowserFieldTextHighlightColor ## CONSUMES + gEfiMdeModulePkgTokenSpaceGuid.PcdBrowserFieldBackgroundHighlightColor ## CONSUMES [Depex] gEfiHiiDatabaseProtocolGuid AND gEfiHiiConfigRoutingProtocolGuid diff --git a/MdeModulePkg/Universal/SetupBrowserDxe/SetupBrowserStr.uni b/MdeModulePkg/Universal/SetupBrowserDxe/SetupBrowserStr.uni new file mode 100644 index 0000000000..bb6414d206 Binary files /dev/null and b/MdeModulePkg/Universal/SetupBrowserDxe/SetupBrowserStr.uni differ diff --git a/MdeModulePkg/Universal/SetupBrowserDxe/Ui.c b/MdeModulePkg/Universal/SetupBrowserDxe/Ui.c new file mode 100644 index 0000000000..7c246b60e1 --- /dev/null +++ b/MdeModulePkg/Universal/SetupBrowserDxe/Ui.c @@ -0,0 +1,4027 @@ +/** @file +Utility functions for User Interface functions. + +Copyright (c) 2004 - 2013, Intel Corporation. All rights reserved.
+This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include "Setup.h" + +LIST_ENTRY gMenuOption; +LIST_ENTRY gMenuList; +MENU_REFRESH_ENTRY *gMenuRefreshHead; // Menu list used for refresh timer opcode. +MENU_REFRESH_ENTRY *gMenuEventGuidRefreshHead; // Menu list used for refresh event guid opcode. + +// +// Search table for UiDisplayMenu() +// +SCAN_CODE_TO_SCREEN_OPERATION gScanCodeToOperation[] = { + { + SCAN_UP, + UiUp, + }, + { + SCAN_DOWN, + UiDown, + }, + { + SCAN_PAGE_UP, + UiPageUp, + }, + { + SCAN_PAGE_DOWN, + UiPageDown, + }, + { + SCAN_ESC, + UiReset, + }, + { + SCAN_LEFT, + UiLeft, + }, + { + SCAN_RIGHT, + UiRight, + } +}; + +UINTN mScanCodeNumber = sizeof (gScanCodeToOperation) / sizeof (gScanCodeToOperation[0]); + +SCREEN_OPERATION_T0_CONTROL_FLAG gScreenOperationToControlFlag[] = { + { + UiNoOperation, + CfUiNoOperation, + }, + { + UiSelect, + CfUiSelect, + }, + { + UiUp, + CfUiUp, + }, + { + UiDown, + CfUiDown, + }, + { + UiLeft, + CfUiLeft, + }, + { + UiRight, + CfUiRight, + }, + { + UiReset, + CfUiReset, + }, + { + UiPageUp, + CfUiPageUp, + }, + { + UiPageDown, + CfUiPageDown + }, + { + UiHotKey, + CfUiHotKey + } +}; + +BOOLEAN mInputError; +BOOLEAN GetLineByWidthFinished = FALSE; + + +/** + Set Buffer to Value for Size bytes. + + @param Buffer Memory to set. + @param Size Number of bytes to set + @param Value Value of the set operation. + +**/ +VOID +SetUnicodeMem ( + IN VOID *Buffer, + IN UINTN Size, + IN CHAR16 Value + ) +{ + CHAR16 *Ptr; + + Ptr = Buffer; + while ((Size--) != 0) { + *(Ptr++) = Value; + } +} + + +/** + Initialize Menu option list. + +**/ +VOID +UiInitMenu ( + VOID + ) +{ + InitializeListHead (&gMenuOption); +} + + +/** + Free Menu option linked list. + +**/ +VOID +UiFreeMenu ( + VOID + ) +{ + UI_MENU_OPTION *MenuOption; + + while (!IsListEmpty (&gMenuOption)) { + MenuOption = MENU_OPTION_FROM_LINK (gMenuOption.ForwardLink); + RemoveEntryList (&MenuOption->Link); + + // + // We allocated space for this description when we did a GetToken, free it here + // + if (MenuOption->Skip != 0) { + // + // For date/time, MenuOption->Description is shared by three Menu Options + // Data format : [01/02/2004] [11:22:33] + // Line number : 0 0 1 0 0 1 + // + FreePool (MenuOption->Description); + } + FreePool (MenuOption); + } +} + + +/** + Create a menu with specified formset GUID and form ID, and add it as a child + of the given parent menu. + + @param Parent The parent of menu to be added. + @param HiiHandle Hii handle related to this formset. + @param FormSetGuid The Formset Guid of menu to be added. + @param FormId The Form ID of menu to be added. + + @return A pointer to the newly added menu or NULL if memory is insufficient. + +**/ +UI_MENU_LIST * +UiAddMenuList ( + IN OUT UI_MENU_LIST *Parent, + IN EFI_HII_HANDLE HiiHandle, + IN EFI_GUID *FormSetGuid, + IN UINT16 FormId + ) +{ + UI_MENU_LIST *MenuList; + + MenuList = AllocateZeroPool (sizeof (UI_MENU_LIST)); + if (MenuList == NULL) { + return NULL; + } + + MenuList->Signature = UI_MENU_LIST_SIGNATURE; + InitializeListHead (&MenuList->ChildListHead); + + MenuList->HiiHandle = HiiHandle; + CopyMem (&MenuList->FormSetGuid, FormSetGuid, sizeof (EFI_GUID)); + MenuList->FormId = FormId; + MenuList->Parent = Parent; + + if (Parent == NULL) { + // + // If parent is not specified, it is the root Form of a Formset + // + InsertTailList (&gMenuList, &MenuList->Link); + } else { + InsertTailList (&Parent->ChildListHead, &MenuList->Link); + } + + return MenuList; +} + + +/** + Search Menu with given FormId, FormSetGuid and Handle in all cached menu list. + + @param Parent The parent of menu to search. + @param Handle Hii handle related to this formset. + @param FormSetGuid The Formset GUID of the menu to search. + @param FormId The Form ID of menu to search. + + @return A pointer to menu found or NULL if not found. + +**/ +UI_MENU_LIST * +UiFindChildMenuList ( + IN UI_MENU_LIST *Parent, + IN EFI_HII_HANDLE Handle, + IN EFI_GUID *FormSetGuid, + IN UINT16 FormId + ) +{ + LIST_ENTRY *Link; + UI_MENU_LIST *Child; + UI_MENU_LIST *MenuList; + + ASSERT (Parent != NULL); + + if (Parent->FormId == FormId && CompareGuid (FormSetGuid, &Parent->FormSetGuid) && Parent->HiiHandle == Handle) { + return Parent; + } + + Link = GetFirstNode (&Parent->ChildListHead); + while (!IsNull (&Parent->ChildListHead, Link)) { + Child = UI_MENU_LIST_FROM_LINK (Link); + + MenuList = UiFindChildMenuList (Child, Handle, FormSetGuid, FormId); + if (MenuList != NULL) { + return MenuList; + } + + Link = GetNextNode (&Parent->ChildListHead, Link); + } + + return NULL; +} + + +/** + Search Menu with given Handle, FormSetGuid and FormId in all cached menu list. + + @param Handle Hii handle related to this formset. + @param FormSetGuid The Formset GUID of the menu to search. + @param FormId The Form ID of menu to search. + + @return A pointer to menu found or NULL if not found. + +**/ +UI_MENU_LIST * +UiFindMenuList ( + IN EFI_HII_HANDLE Handle, + IN EFI_GUID *FormSetGuid, + IN UINT16 FormId + ) +{ + LIST_ENTRY *Link; + UI_MENU_LIST *MenuList; + UI_MENU_LIST *Child; + + Link = GetFirstNode (&gMenuList); + while (!IsNull (&gMenuList, Link)) { + MenuList = UI_MENU_LIST_FROM_LINK (Link); + + Child = UiFindChildMenuList(MenuList, Handle, FormSetGuid, FormId); + if (Child != NULL) { + + // + // If this form already in the menu history list, + // just free the list between old this form. + // + UiFreeMenuList(&Child->ChildListHead); + return Child; + } + + Link = GetNextNode (&gMenuList, Link); + } + + return NULL; +} + +/** + Free Menu list linked list. + + @param MenuListHead One Menu list point in the menu list. + +**/ +VOID +UiFreeMenuList ( + LIST_ENTRY *MenuListHead + ) +{ + UI_MENU_LIST *MenuList; + + while (!IsListEmpty (MenuListHead)) { + MenuList = UI_MENU_LIST_FROM_LINK (MenuListHead->ForwardLink); + RemoveEntryList (&MenuList->Link); + + UiFreeMenuList(&MenuList->ChildListHead); + FreePool (MenuList); + } + +} + +/** + Free Menu option linked list. + +**/ +VOID +UiFreeRefreshList ( + VOID + ) +{ + MENU_REFRESH_ENTRY *OldMenuRefreshEntry; + + while (gMenuRefreshHead != NULL) { + OldMenuRefreshEntry = gMenuRefreshHead->Next; + FreePool (gMenuRefreshHead); + gMenuRefreshHead = OldMenuRefreshEntry; + } + + while (gMenuEventGuidRefreshHead != NULL) { + OldMenuRefreshEntry = gMenuEventGuidRefreshHead->Next; + if (gMenuEventGuidRefreshHead != NULL) { + gBS->CloseEvent(gMenuEventGuidRefreshHead->Event); + } + FreePool (gMenuEventGuidRefreshHead); + gMenuEventGuidRefreshHead = OldMenuRefreshEntry; + } +} + + +/** + Process option string for date/time opcode. + + @param MenuOption Menu option point to date/time. + @param OptionString Option string input for process. + @param AddOptCol Whether need to update MenuOption->OptCol. + +**/ +VOID +ProcessStringForDateTime ( + UI_MENU_OPTION *MenuOption, + CHAR16 *OptionString, + BOOLEAN AddOptCol + ) +{ + UINTN Index; + UINTN Count; + FORM_BROWSER_STATEMENT *Statement; + + ASSERT (MenuOption != NULL && OptionString != NULL); + + Statement = MenuOption->ThisTag; + + // + // If leading spaces on OptionString - remove the spaces + // + for (Index = 0; OptionString[Index] == L' '; Index++) { + // + // Base on the blockspace to get the option column info. + // + if (AddOptCol) { + MenuOption->OptCol++; + } + } + + for (Count = 0; OptionString[Index] != CHAR_NULL; Index++) { + OptionString[Count] = OptionString[Index]; + Count++; + } + OptionString[Count] = CHAR_NULL; + + // + // Enable to suppress field in the opcode base on the flag. + // + if (Statement->Operand == EFI_IFR_DATE_OP) { + // + // OptionString format is: <**: **: ****> + // |month|day|year| + // 4 3 5 + // + if ((Statement->Flags & EFI_QF_DATE_MONTH_SUPPRESS) && (MenuOption->Sequence == 0)) { + // + // At this point, only "<**:" in the optionstring. + // Clean the day's ** field, after clean, the format is "< :" + // + SetUnicodeMem (&OptionString[1], 2, L' '); + } else if ((Statement->Flags & EFI_QF_DATE_DAY_SUPPRESS) && (MenuOption->Sequence == 1)) { + // + // At this point, only "**:" in the optionstring. + // Clean the month's "**" field, after clean, the format is " :" + // + SetUnicodeMem (&OptionString[0], 2, L' '); + } else if ((Statement->Flags & EFI_QF_DATE_YEAR_SUPPRESS) && (MenuOption->Sequence == 2)) { + // + // At this point, only "****>" in the optionstring. + // Clean the year's "****" field, after clean, the format is " >" + // + SetUnicodeMem (&OptionString[0], 4, L' '); + } + } else if (Statement->Operand == EFI_IFR_TIME_OP) { + // + // OptionString format is: <**: **: **> + // |hour|minute|second| + // 4 3 3 + // + if ((Statement->Flags & QF_TIME_HOUR_SUPPRESS) && (MenuOption->Sequence == 0)) { + // + // At this point, only "<**:" in the optionstring. + // Clean the hour's ** field, after clean, the format is "< :" + // + SetUnicodeMem (&OptionString[1], 2, L' '); + } else if ((Statement->Flags & QF_TIME_MINUTE_SUPPRESS) && (MenuOption->Sequence == 1)) { + // + // At this point, only "**:" in the optionstring. + // Clean the minute's "**" field, after clean, the format is " :" + // + SetUnicodeMem (&OptionString[0], 2, L' '); + } else if ((Statement->Flags & QF_TIME_SECOND_SUPPRESS) && (MenuOption->Sequence == 2)) { + // + // At this point, only "**>" in the optionstring. + // Clean the second's "**" field, after clean, the format is " >" + // + SetUnicodeMem (&OptionString[0], 2, L' '); + } + } +} + +/** + Refresh question. + + @param MenuRefreshEntry Menu refresh structure which has info about the refresh question. +**/ +EFI_STATUS +RefreshQuestion ( + IN MENU_REFRESH_ENTRY *MenuRefreshEntry + ) +{ + CHAR16 *OptionString; + EFI_STATUS Status; + UI_MENU_SELECTION *Selection; + FORM_BROWSER_STATEMENT *Question; + + Selection = MenuRefreshEntry->Selection; + Question = MenuRefreshEntry->MenuOption->ThisTag; + + Status = GetQuestionValue (Selection->FormSet, Selection->Form, Question, GetSetValueWithHiiDriver); + if (EFI_ERROR (Status)) { + return Status; + } + + OptionString = NULL; + ProcessOptions (Selection, MenuRefreshEntry->MenuOption, FALSE, &OptionString); + + if (OptionString != NULL) { + // + // If old Text is longer than new string, need to clean the old string before paint the newer. + // This option is no need for time/date opcode, because time/data opcode has fixed string length. + // + if ((MenuRefreshEntry->MenuOption->ThisTag->Operand != EFI_IFR_DATE_OP) && + (MenuRefreshEntry->MenuOption->ThisTag->Operand != EFI_IFR_TIME_OP)) { + ClearLines ( + MenuRefreshEntry->CurrentColumn, + MenuRefreshEntry->CurrentColumn + gOptionBlockWidth - 1, + MenuRefreshEntry->CurrentRow, + MenuRefreshEntry->CurrentRow, + PcdGet8 (PcdBrowserFieldTextColor) | FIELD_BACKGROUND + ); + } + + gST->ConOut->SetAttribute (gST->ConOut, MenuRefreshEntry->CurrentAttribute); + ProcessStringForDateTime(MenuRefreshEntry->MenuOption, OptionString, FALSE); + PrintStringAt (MenuRefreshEntry->CurrentColumn, MenuRefreshEntry->CurrentRow, OptionString); + FreePool (OptionString); + } + + // + // Question value may be changed, need invoke its Callback() + // + Status = ProcessCallBackFunction (Selection, Question, EFI_BROWSER_ACTION_CHANGING, FALSE); + + return Status; +} + +/** + Refresh the question which has refresh guid event attribute. + + @param Event The event which has this function related. + @param Context The input context info related to this event or the status code return to the caller. +**/ +VOID +EFIAPI +RefreshQuestionNotify( + IN EFI_EVENT Event, + IN VOID *Context + ) +{ + MENU_REFRESH_ENTRY *MenuRefreshEntry; + UI_MENU_SELECTION *Selection; + + // + // Reset FormPackage update flag + // + mHiiPackageListUpdated = FALSE; + + MenuRefreshEntry = (MENU_REFRESH_ENTRY *)Context; + ASSERT (MenuRefreshEntry != NULL); + Selection = MenuRefreshEntry->Selection; + + RefreshQuestion (MenuRefreshEntry); + + if (mHiiPackageListUpdated) { + // + // Package list is updated, force to reparse IFR binary of target Formset + // + mHiiPackageListUpdated = FALSE; + Selection->Action = UI_ACTION_REFRESH_FORMSET; + } +} + + +/** + Refresh screen. + +**/ +EFI_STATUS +RefreshForm ( + VOID + ) +{ + MENU_REFRESH_ENTRY *MenuRefreshEntry; + EFI_STATUS Status; + UI_MENU_SELECTION *Selection; + + if (gMenuRefreshHead != NULL) { + // + // call from refresh interval process. + // + MenuRefreshEntry = gMenuRefreshHead; + Selection = MenuRefreshEntry->Selection; + // + // Reset FormPackage update flag + // + mHiiPackageListUpdated = FALSE; + + do { + Status = RefreshQuestion (MenuRefreshEntry); + if (EFI_ERROR (Status)) { + return Status; + } + + MenuRefreshEntry = MenuRefreshEntry->Next; + + } while (MenuRefreshEntry != NULL); + + if (mHiiPackageListUpdated) { + // + // Package list is updated, force to reparse IFR binary of target Formset + // + mHiiPackageListUpdated = FALSE; + Selection->Action = UI_ACTION_REFRESH_FORMSET; + return EFI_SUCCESS; + } + } + + return EFI_TIMEOUT; +} + + +/** + Wait for a given event to fire, or for an optional timeout to expire. + + @param Event The event to wait for + @param Timeout An optional timeout value in 100 ns units. + @param RefreshInterval Menu refresh interval (in seconds). + + @retval EFI_SUCCESS Event fired before Timeout expired. + @retval EFI_TIME_OUT Timout expired before Event fired. + +**/ +EFI_STATUS +UiWaitForSingleEvent ( + IN EFI_EVENT Event, + IN UINT64 Timeout, OPTIONAL + IN UINT8 RefreshInterval OPTIONAL + ) +{ + EFI_STATUS Status; + UINTN Index; + EFI_EVENT TimerEvent; + EFI_EVENT WaitList[2]; + + if (Timeout != 0) { + // + // Create a timer event + // + Status = gBS->CreateEvent (EVT_TIMER, 0, NULL, NULL, &TimerEvent); + if (!EFI_ERROR (Status)) { + // + // Set the timer event + // + gBS->SetTimer ( + TimerEvent, + TimerRelative, + Timeout + ); + + // + // Wait for the original event or the timer + // + WaitList[0] = Event; + WaitList[1] = TimerEvent; + Status = gBS->WaitForEvent (2, WaitList, &Index); + gBS->CloseEvent (TimerEvent); + + // + // If the timer expired, change the return to timed out + // + if (!EFI_ERROR (Status) && Index == 1) { + Status = EFI_TIMEOUT; + } + } + } else { + // + // Update screen every second + // + if (RefreshInterval == 0) { + Timeout = ONE_SECOND; + } else { + Timeout = RefreshInterval * ONE_SECOND; + } + + do { + Status = gBS->CreateEvent (EVT_TIMER, 0, NULL, NULL, &TimerEvent); + + // + // Set the timer event + // + gBS->SetTimer ( + TimerEvent, + TimerRelative, + Timeout + ); + + // + // Wait for the original event or the timer + // + WaitList[0] = Event; + WaitList[1] = TimerEvent; + Status = gBS->WaitForEvent (2, WaitList, &Index); + + // + // If the timer expired, update anything that needs a refresh and keep waiting + // + if (!EFI_ERROR (Status) && Index == 1) { + Status = EFI_TIMEOUT; + if (RefreshInterval != 0) { + Status = RefreshForm (); + } + } + + gBS->CloseEvent (TimerEvent); + } while (Status == EFI_TIMEOUT); + } + + return Status; +} + + +/** + Add one menu option by specified description and context. + + @param String String description for this option. + @param Handle Hii handle for the package list. + @param Form The form this statement belong to. + @param Statement Statement of this Menu Option. + @param NumberOfLines Display lines for this Menu Option. + @param MenuItemCount The index for this Option in the Menu. + + @retval Pointer Pointer to the added Menu Option. + +**/ +UI_MENU_OPTION * +UiAddMenuOption ( + IN CHAR16 *String, + IN EFI_HII_HANDLE Handle, + IN FORM_BROWSER_FORM *Form, + IN FORM_BROWSER_STATEMENT *Statement, + IN UINT16 NumberOfLines, + IN UINT16 MenuItemCount + ) +{ + UI_MENU_OPTION *MenuOption; + UINTN Index; + UINTN Count; + + Count = 1; + MenuOption = NULL; + + if (Statement->Operand == EFI_IFR_DATE_OP || Statement->Operand == EFI_IFR_TIME_OP) { + // + // Add three MenuOptions for Date/Time + // Data format : [01/02/2004] [11:22:33] + // Line number : 0 0 1 0 0 1 + // + NumberOfLines = 0; + Count = 3; + + if (Statement->Storage == NULL) { + // + // For RTC type of date/time, set default refresh interval to be 1 second + // + if (Statement->RefreshInterval == 0) { + Statement->RefreshInterval = 1; + } + } + } + + for (Index = 0; Index < Count; Index++) { + MenuOption = AllocateZeroPool (sizeof (UI_MENU_OPTION)); + ASSERT (MenuOption); + + MenuOption->Signature = UI_MENU_OPTION_SIGNATURE; + MenuOption->Description = String; + MenuOption->Handle = Handle; + MenuOption->ThisTag = Statement; + MenuOption->EntryNumber = MenuItemCount; + + if (Index == 2) { + // + // Override LineNumber for the MenuOption in Date/Time sequence + // + MenuOption->Skip = 1; + } else { + MenuOption->Skip = NumberOfLines; + } + MenuOption->Sequence = Index; + + if (EvaluateExpressionList(Statement->Expression, FALSE, NULL, NULL) == ExpressGrayOut ) { + MenuOption->GrayOut = TRUE; + } else { + MenuOption->GrayOut = FALSE; + } + + // + // If the form or the question has the lock attribute, deal same as grayout. + // + if (Form->Locked || Statement->Locked) { + MenuOption->GrayOut = TRUE; + } + + switch (Statement->Operand) { + case EFI_IFR_ORDERED_LIST_OP: + case EFI_IFR_ONE_OF_OP: + case EFI_IFR_NUMERIC_OP: + case EFI_IFR_TIME_OP: + case EFI_IFR_DATE_OP: + case EFI_IFR_CHECKBOX_OP: + case EFI_IFR_PASSWORD_OP: + case EFI_IFR_STRING_OP: + // + // User could change the value of these items + // + MenuOption->IsQuestion = TRUE; + break; + + case EFI_IFR_TEXT_OP: + if (FeaturePcdGet (PcdBrowserGrayOutTextStatement)) { + // + // Initializing GrayOut option as TRUE for Text setup options + // so that those options will be Gray in colour and un selectable. + // + MenuOption->GrayOut = TRUE; + } + // + // break skipped on purpose + // + default: + MenuOption->IsQuestion = FALSE; + break; + } + + if ((Statement->ValueExpression != NULL) || + ((Statement->QuestionFlags & EFI_IFR_FLAG_READ_ONLY) != 0)) { + MenuOption->ReadOnly = TRUE; + if (FeaturePcdGet (PcdBrowerGrayOutReadOnlyMenu)) { + MenuOption->GrayOut = TRUE; + } + } + + InsertTailList (&gMenuOption, &MenuOption->Link); + } + + return MenuOption; +} + + +/** + Routine used to abstract a generic dialog interface and return the selected key or string + + @param NumberOfLines The number of lines for the dialog box + @param HotKey Defines whether a single character is parsed + (TRUE) and returned in KeyValue or a string is + returned in StringBuffer. Two special characters + are considered when entering a string, a SCAN_ESC + and an CHAR_CARRIAGE_RETURN. SCAN_ESC terminates + string input and returns + @param MaximumStringSize The maximum size in bytes of a typed in string + (each character is a CHAR16) and the minimum + string returned is two bytes + @param StringBuffer The passed in pointer to the buffer which will + hold the typed in string if HotKey is FALSE + @param KeyValue The EFI_KEY value returned if HotKey is TRUE.. + @param ... A series of (quantity == NumberOfLines) text + strings which will be used to construct the dialog + box + + @retval EFI_SUCCESS Displayed dialog and received user interaction + @retval EFI_INVALID_PARAMETER One of the parameters was invalid (e.g. + (StringBuffer == NULL) && (HotKey == FALSE)) + @retval EFI_DEVICE_ERROR User typed in an ESC character to exit the routine + +**/ +EFI_STATUS +EFIAPI +CreateDialog ( + IN UINTN NumberOfLines, + IN BOOLEAN HotKey, + IN UINTN MaximumStringSize, + OUT CHAR16 *StringBuffer, + OUT EFI_INPUT_KEY *KeyValue, + ... + ) +{ + VA_LIST Marker; + UINTN Count; + EFI_INPUT_KEY Key; + UINTN LargestString; + CHAR16 *TempString; + CHAR16 *BufferedString; + CHAR16 *StackString; + CHAR16 KeyPad[2]; + UINTN Start; + UINTN Top; + UINTN Index; + EFI_STATUS Status; + BOOLEAN SelectionComplete; + UINTN InputOffset; + UINTN CurrentAttribute; + UINTN DimensionsWidth; + UINTN DimensionsHeight; + + DimensionsWidth = gScreenDimensions.RightColumn - gScreenDimensions.LeftColumn; + DimensionsHeight = gScreenDimensions.BottomRow - gScreenDimensions.TopRow; + + SelectionComplete = FALSE; + InputOffset = 0; + TempString = AllocateZeroPool (MaximumStringSize * 2); + BufferedString = AllocateZeroPool (MaximumStringSize * 2); + CurrentAttribute = gST->ConOut->Mode->Attribute; + + ASSERT (TempString); + ASSERT (BufferedString); + + // + // Zero the outgoing buffer + // + ZeroMem (StringBuffer, MaximumStringSize); + + if (HotKey) { + if (KeyValue == NULL) { + return EFI_INVALID_PARAMETER; + } + } else { + if (StringBuffer == NULL) { + return EFI_INVALID_PARAMETER; + } + } + // + // Disable cursor + // + gST->ConOut->EnableCursor (gST->ConOut, FALSE); + + LargestString = 0; + + VA_START (Marker, KeyValue); + + // + // Determine the largest string in the dialog box + // Notice we are starting with 1 since String is the first string + // + for (Count = 0; Count < NumberOfLines; Count++) { + StackString = VA_ARG (Marker, CHAR16 *); + + if (StackString[0] == L' ') { + InputOffset = Count + 1; + } + + if ((GetStringWidth (StackString) / 2) > LargestString) { + // + // Size of the string visually and subtract the width by one for the null-terminator + // + LargestString = (GetStringWidth (StackString) / 2); + } + } + VA_END (Marker); + + Start = (DimensionsWidth - LargestString - 2) / 2 + gScreenDimensions.LeftColumn + 1; + Top = ((DimensionsHeight - NumberOfLines - 2) / 2) + gScreenDimensions.TopRow - 1; + + Count = 0; + + // + // Display the Popup + // + VA_START (Marker, KeyValue); + CreateSharedPopUp (LargestString, NumberOfLines, Marker); + VA_END (Marker); + + // + // Take the first key typed and report it back? + // + if (HotKey) { + Status = WaitForKeyStroke (&Key); + ASSERT_EFI_ERROR (Status); + CopyMem (KeyValue, &Key, sizeof (EFI_INPUT_KEY)); + + } else { + do { + Status = WaitForKeyStroke (&Key); + + switch (Key.UnicodeChar) { + case CHAR_NULL: + switch (Key.ScanCode) { + case SCAN_ESC: + FreePool (TempString); + FreePool (BufferedString); + gST->ConOut->SetAttribute (gST->ConOut, CurrentAttribute); + gST->ConOut->EnableCursor (gST->ConOut, TRUE); + return EFI_DEVICE_ERROR; + + default: + break; + } + + break; + + case CHAR_CARRIAGE_RETURN: + SelectionComplete = TRUE; + FreePool (TempString); + FreePool (BufferedString); + gST->ConOut->SetAttribute (gST->ConOut, CurrentAttribute); + gST->ConOut->EnableCursor (gST->ConOut, TRUE); + return EFI_SUCCESS; + break; + + case CHAR_BACKSPACE: + if (StringBuffer[0] != CHAR_NULL) { + for (Index = 0; StringBuffer[Index] != CHAR_NULL; Index++) { + TempString[Index] = StringBuffer[Index]; + } + // + // Effectively truncate string by 1 character + // + TempString[Index - 1] = CHAR_NULL; + StrCpy (StringBuffer, TempString); + } + // + // break skipped on purpose + // + + default: + // + // If it is the beginning of the string, don't worry about checking maximum limits + // + if ((StringBuffer[0] == CHAR_NULL) && (Key.UnicodeChar != CHAR_BACKSPACE)) { + StrnCpy (StringBuffer, &Key.UnicodeChar, 1); + StrnCpy (TempString, &Key.UnicodeChar, 1); + } else if ((GetStringWidth (StringBuffer) < MaximumStringSize) && (Key.UnicodeChar != CHAR_BACKSPACE)) { + KeyPad[0] = Key.UnicodeChar; + KeyPad[1] = CHAR_NULL; + StrCat (StringBuffer, KeyPad); + StrCat (TempString, KeyPad); + } + // + // If the width of the input string is now larger than the screen, we nee to + // adjust the index to start printing portions of the string + // + SetUnicodeMem (BufferedString, LargestString, L' '); + + PrintStringAt (Start + 1, Top + InputOffset, BufferedString); + + if ((GetStringWidth (StringBuffer) / 2) > (DimensionsWidth - 2)) { + Index = (GetStringWidth (StringBuffer) / 2) - DimensionsWidth + 2; + } else { + Index = 0; + } + + for (Count = 0; Index + 1 < GetStringWidth (StringBuffer) / 2; Index++, Count++) { + BufferedString[Count] = StringBuffer[Index]; + } + + PrintStringAt (Start + 1, Top + InputOffset, BufferedString); + break; + } + } while (!SelectionComplete); + } + + gST->ConOut->SetAttribute (gST->ConOut, CurrentAttribute); + gST->ConOut->EnableCursor (gST->ConOut, TRUE); + return EFI_SUCCESS; +} + +/** + Draw a pop up windows based on the dimension, number of lines and + strings specified. + + @param RequestedWidth The width of the pop-up. + @param NumberOfLines The number of lines. + @param Marker The variable argument list for the list of string to be printed. + +**/ +VOID +CreateSharedPopUp ( + IN UINTN RequestedWidth, + IN UINTN NumberOfLines, + IN VA_LIST Marker + ) +{ + UINTN Index; + UINTN Count; + CHAR16 Character; + UINTN Start; + UINTN End; + UINTN Top; + UINTN Bottom; + CHAR16 *String; + UINTN DimensionsWidth; + UINTN DimensionsHeight; + + DimensionsWidth = gScreenDimensions.RightColumn - gScreenDimensions.LeftColumn; + DimensionsHeight = gScreenDimensions.BottomRow - gScreenDimensions.TopRow; + + gST->ConOut->SetAttribute (gST->ConOut, POPUP_TEXT | POPUP_BACKGROUND); + + if ((RequestedWidth + 2) > DimensionsWidth) { + RequestedWidth = DimensionsWidth - 2; + } + + // + // Subtract the PopUp width from total Columns, allow for one space extra on + // each end plus a border. + // + Start = (DimensionsWidth - RequestedWidth - 2) / 2 + gScreenDimensions.LeftColumn + 1; + End = Start + RequestedWidth + 1; + + Top = ((DimensionsHeight - NumberOfLines - 2) / 2) + gScreenDimensions.TopRow - 1; + Bottom = Top + NumberOfLines + 2; + + Character = BOXDRAW_DOWN_RIGHT; + PrintCharAt (Start, Top, Character); + Character = BOXDRAW_HORIZONTAL; + for (Index = Start; Index + 2 < End; Index++) { + PrintChar (Character); + } + + Character = BOXDRAW_DOWN_LEFT; + PrintChar (Character); + Character = BOXDRAW_VERTICAL; + + Count = 0; + for (Index = Top; Index + 2 < Bottom; Index++, Count++) { + String = VA_ARG (Marker, CHAR16*); + + // + // This will clear the background of the line - we never know who might have been + // here before us. This differs from the next clear in that it used the non-reverse + // video for normal printing. + // + if (GetStringWidth (String) / 2 > 1) { + ClearLines (Start, End, Index + 1, Index + 1, POPUP_TEXT | POPUP_BACKGROUND); + } + + // + // Passing in a space results in the assumption that this is where typing will occur + // + if (String[0] == L' ') { + ClearLines (Start + 1, End - 1, Index + 1, Index + 1, POPUP_INVERSE_TEXT | POPUP_INVERSE_BACKGROUND); + } + + // + // Passing in a NULL results in a blank space + // + if (String[0] == CHAR_NULL) { + ClearLines (Start, End, Index + 1, Index + 1, POPUP_TEXT | POPUP_BACKGROUND); + } + + PrintStringAt ( + ((DimensionsWidth - GetStringWidth (String) / 2) / 2) + gScreenDimensions.LeftColumn + 1, + Index + 1, + String + ); + gST->ConOut->SetAttribute (gST->ConOut, POPUP_TEXT | POPUP_BACKGROUND); + PrintCharAt (Start, Index + 1, Character); + PrintCharAt (End - 1, Index + 1, Character); + } + + Character = BOXDRAW_UP_RIGHT; + PrintCharAt (Start, Bottom - 1, Character); + Character = BOXDRAW_HORIZONTAL; + for (Index = Start; Index + 2 < End; Index++) { + PrintChar (Character); + } + + Character = BOXDRAW_UP_LEFT; + PrintChar (Character); +} + +/** + Draw a pop up windows based on the dimension, number of lines and + strings specified. + + @param RequestedWidth The width of the pop-up. + @param NumberOfLines The number of lines. + @param ... A series of text strings that displayed in the pop-up. + +**/ +VOID +EFIAPI +CreateMultiStringPopUp ( + IN UINTN RequestedWidth, + IN UINTN NumberOfLines, + ... + ) +{ + VA_LIST Marker; + + VA_START (Marker, NumberOfLines); + + CreateSharedPopUp (RequestedWidth, NumberOfLines, Marker); + + VA_END (Marker); +} + + +/** + Update status bar on the bottom of menu. + + @param Selection Current Selction info. + @param MessageType The type of message to be shown. + @param Flags The flags in Question header. + @param State Set or clear. + +**/ +VOID +UpdateStatusBar ( + IN UI_MENU_SELECTION *Selection, + IN UINTN MessageType, + IN UINT8 Flags, + IN BOOLEAN State + ) +{ + UINTN Index; + CHAR16 *NvUpdateMessage; + CHAR16 *InputErrorMessage; + LIST_ENTRY *Link; + FORM_BROWSER_FORMSET *LocalFormSet; + FORM_BROWSER_STATEMENT *Question; + + NvUpdateMessage = GetToken (STRING_TOKEN (NV_UPDATE_MESSAGE), gHiiHandle); + InputErrorMessage = GetToken (STRING_TOKEN (INPUT_ERROR_MESSAGE), gHiiHandle); + + switch (MessageType) { + case INPUT_ERROR: + if (State) { + gST->ConOut->SetAttribute (gST->ConOut, ERROR_TEXT); + PrintStringAt ( + gScreenDimensions.LeftColumn + gPromptBlockWidth, + gScreenDimensions.BottomRow - 1, + InputErrorMessage + ); + mInputError = TRUE; + } else { + gST->ConOut->SetAttribute (gST->ConOut, PcdGet8 (PcdBrowserFieldTextHighlightColor)); + for (Index = 0; Index < (GetStringWidth (InputErrorMessage) - 2) / 2; Index++) { + PrintAt (gScreenDimensions.LeftColumn + gPromptBlockWidth + Index, gScreenDimensions.BottomRow - 1, L" "); + } + + mInputError = FALSE; + } + break; + + case NV_UPDATE_REQUIRED: + // + // Global setting support. Show configuration change on every form. + // + if (State) { + gResetRequired = (BOOLEAN) (gResetRequired | ((Flags & EFI_IFR_FLAG_RESET_REQUIRED) == EFI_IFR_FLAG_RESET_REQUIRED)); + + if (Selection != NULL && Selection->Statement != NULL) { + Question = Selection->Statement; + if (Question->Storage != NULL || Question->Operand == EFI_IFR_DATE_OP || Question->Operand == EFI_IFR_TIME_OP) { + // + // Update only for Question value that need to be saved into Storage. + // + Selection->Form->NvUpdateRequired = TRUE; + } + } + + if (Selection == NULL || IsNvUpdateRequired (Selection->FormSet)) { + gST->ConOut->SetAttribute (gST->ConOut, INFO_TEXT); + PrintStringAt ( + gScreenDimensions.LeftColumn + gPromptBlockWidth + gOptionBlockWidth, + gScreenDimensions.BottomRow - 1, + NvUpdateMessage + ); + } + } else { + gST->ConOut->SetAttribute (gST->ConOut, PcdGet8 (PcdBrowserFieldTextHighlightColor)); + for (Index = 0; Index < (GetStringWidth (NvUpdateMessage) - 2) / 2; Index++) { + PrintAt ( + (gScreenDimensions.LeftColumn + gPromptBlockWidth + gOptionBlockWidth + Index), + gScreenDimensions.BottomRow - 1, + L" " + ); + } + } + break; + + case REFRESH_STATUS_BAR: + if (mInputError) { + UpdateStatusBar (Selection, INPUT_ERROR, Flags, TRUE); + } + + switch (gBrowserSettingScope) { + case SystemLevel: + // + // Check the maintain list to see whether there is any change. + // + Link = GetFirstNode (&gBrowserFormSetList); + while (!IsNull (&gBrowserFormSetList, Link)) { + LocalFormSet = FORM_BROWSER_FORMSET_FROM_LINK (Link); + if (IsNvUpdateRequired(LocalFormSet)) { + UpdateStatusBar (NULL, NV_UPDATE_REQUIRED, Flags, TRUE); + break; + } + Link = GetNextNode (&gBrowserFormSetList, Link); + } + break; + case FormSetLevel: + case FormLevel: + UpdateStatusBar (Selection, NV_UPDATE_REQUIRED, Flags, TRUE); + default: + break; + } + + break; + + default: + break; + } + + FreePool (InputErrorMessage); + FreePool (NvUpdateMessage); + return ; +} + + +/** + Get the supported width for a particular op-code + + @param Statement The FORM_BROWSER_STATEMENT structure passed in. + @param Handle The handle in the HII database being used + + @return Returns the number of CHAR16 characters that is support. + +**/ +UINT16 +GetWidth ( + IN FORM_BROWSER_STATEMENT *Statement, + IN EFI_HII_HANDLE Handle + ) +{ + CHAR16 *String; + UINTN Size; + UINT16 Width; + + Size = 0; + + // + // See if the second text parameter is really NULL + // + if ((Statement->Operand == EFI_IFR_TEXT_OP) && (Statement->TextTwo != 0)) { + String = GetToken (Statement->TextTwo, Handle); + Size = StrLen (String); + FreePool (String); + } + + if ((Statement->Operand == EFI_IFR_SUBTITLE_OP) || + (Statement->Operand == EFI_IFR_REF_OP) || + (Statement->Operand == EFI_IFR_PASSWORD_OP) || + (Statement->Operand == EFI_IFR_ACTION_OP) || + (Statement->Operand == EFI_IFR_RESET_BUTTON_OP) || + // + // Allow a wide display if text op-code and no secondary text op-code + // + ((Statement->Operand == EFI_IFR_TEXT_OP) && (Size == 0)) + ) { + Width = (UINT16) (gPromptBlockWidth + gOptionBlockWidth); + } else { + Width = (UINT16) gPromptBlockWidth; + } + + if (Statement->InSubtitle) { + Width -= SUBTITLE_INDENT; + } + + return (UINT16) (Width - LEFT_SKIPPED_COLUMNS); +} + +/** + Will copy LineWidth amount of a string in the OutputString buffer and return the + number of CHAR16 characters that were copied into the OutputString buffer. + The output string format is: + Glyph Info + String info + '\0'. + + In the code, it deals \r,\n,\r\n same as \n\r, also it not process the \r or \g. + + @param InputString String description for this option. + @param LineWidth Width of the desired string to extract in CHAR16 + characters + @param GlyphWidth The glyph width of the begin of the char in the string. + @param Index Where in InputString to start the copy process + @param OutputString Buffer to copy the string into + + @return Returns the number of CHAR16 characters that were copied into the OutputString + buffer, include extra glyph info and '\0' info. + +**/ +UINT16 +GetLineByWidth ( + IN CHAR16 *InputString, + IN UINT16 LineWidth, + IN OUT UINT16 *GlyphWidth, + IN OUT UINTN *Index, + OUT CHAR16 **OutputString + ) +{ + UINT16 StrOffset; + UINT16 GlyphOffset; + UINT16 OriginalGlyphWidth; + BOOLEAN ReturnFlag; + UINT16 LastSpaceOffset; + UINT16 LastGlyphWidth; + + if (InputString == NULL || Index == NULL || OutputString == NULL) { + return 0; + } + + if (LineWidth == 0 || *GlyphWidth == 0) { + return 0; + } + + // + // Save original glyph width. + // + OriginalGlyphWidth = *GlyphWidth; + LastGlyphWidth = OriginalGlyphWidth; + ReturnFlag = FALSE; + LastSpaceOffset = 0; + + // + // 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. + // To avoid displaying this empty line in screen, just skip the two CHARs here. + // + if ((InputString[*Index] == NARROW_CHAR) && (InputString[*Index + 1] == CHAR_CARRIAGE_RETURN)) { + *Index = *Index + 2; + } + + // + // Fast-forward the string and see if there is a carriage-return in the string + // + for (StrOffset = 0, GlyphOffset = 0; GlyphOffset <= LineWidth; StrOffset++) { + switch (InputString[*Index + StrOffset]) { + case NARROW_CHAR: + *GlyphWidth = 1; + break; + + case WIDE_CHAR: + *GlyphWidth = 2; + break; + + case CHAR_CARRIAGE_RETURN: + case CHAR_LINEFEED: + case CHAR_NULL: + ReturnFlag = TRUE; + break; + + default: + GlyphOffset = GlyphOffset + *GlyphWidth; + + // + // Record the last space info in this line. Will be used in rewind. + // + if ((InputString[*Index + StrOffset] == CHAR_SPACE) && (GlyphOffset <= LineWidth)) { + LastSpaceOffset = StrOffset; + LastGlyphWidth = *GlyphWidth; + } + break; + } + + if (ReturnFlag) { + break; + } + } + + // + // Rewind the string from the maximum size until we see a space to break the line + // + if (GlyphOffset > LineWidth) { + // + // Rewind the string to last space char in this line. + // + if (LastSpaceOffset != 0) { + StrOffset = LastSpaceOffset; + *GlyphWidth = LastGlyphWidth; + } else { + // + // Roll back to last char in the line width. + // + StrOffset--; + } + } + + // + // The CHAR_NULL has process last time, this time just return 0 to stand for the end. + // + if (StrOffset == 0 && (InputString[*Index + StrOffset] == CHAR_NULL)) { + return 0; + } + + // + // Need extra glyph info and '\0' info, so +2. + // + *OutputString = AllocateZeroPool (((UINTN) (StrOffset + 2) * sizeof(CHAR16))); + if (*OutputString == NULL) { + return 0; + } + + // + // Save the glyph info at the begin of the string, will used by Print function. + // + if (OriginalGlyphWidth == 1) { + *(*OutputString) = NARROW_CHAR; + } else { + *(*OutputString) = WIDE_CHAR; + } + + CopyMem ((*OutputString) + 1, &InputString[*Index], StrOffset * sizeof(CHAR16)); + + if (InputString[*Index + StrOffset] == CHAR_SPACE) { + // + // Skip the space info at the begin of next line. + // + *Index = (UINT16) (*Index + StrOffset + 1); + } else if (InputString[*Index + StrOffset] == CHAR_LINEFEED) { + // + // Skip the /n or /n/r info. + // + if (InputString[*Index + StrOffset + 1] == CHAR_CARRIAGE_RETURN) { + *Index = (UINT16) (*Index + StrOffset + 2); + } else { + *Index = (UINT16) (*Index + StrOffset + 1); + } + } else if (InputString[*Index + StrOffset] == CHAR_CARRIAGE_RETURN) { + // + // Skip the /r or /r/n info. + // + if (InputString[*Index + StrOffset + 1] == CHAR_LINEFEED) { + *Index = (UINT16) (*Index + StrOffset + 2); + } else { + *Index = (UINT16) (*Index + StrOffset + 1); + } + } else { + *Index = (UINT16) (*Index + StrOffset); + } + + // + // Include extra glyph info and '\0' info, so +2. + // + return StrOffset + 2; +} + + +/** + Update display lines for a Menu Option. + + @param Selection The user's selection. + @param MenuOption The MenuOption to be checked. + +**/ +VOID +UpdateOptionSkipLines ( + IN UI_MENU_SELECTION *Selection, + IN UI_MENU_OPTION *MenuOption + ) +{ + UINTN Index; + UINT16 Width; + UINTN Row; + UINTN OriginalRow; + CHAR16 *OutputString; + CHAR16 *OptionString; + UINT16 GlyphWidth; + + Row = 0; + OptionString = NULL; + Width = (UINT16) gOptionBlockWidth; + OriginalRow = 0; + GlyphWidth = 1; + + ProcessOptions (Selection, MenuOption, FALSE, &OptionString); + if (OptionString == NULL) { + return; + } + + for (Index = 0; GetLineByWidth (OptionString, Width, &GlyphWidth, &Index, &OutputString) != 0x0000;) { + // + // If there is more string to process print on the next row and increment the Skip value + // + if (StrLen (&OptionString[Index]) != 0) { + Row++; + // + // Since the Number of lines for this menu entry may or may not be reflected accurately + // since the prompt might be 1 lines and option might be many, and vice versa, we need to do + // some testing to ensure we are keeping this in-sync. + // + // If the difference in rows is greater than or equal to the skip value, increase the skip value + // + if ((Row - OriginalRow) >= MenuOption->Skip) { + MenuOption->Skip++; + } + } + + FreePool (OutputString); + } + + if (OptionString != NULL) { + FreePool (OptionString); + } +} + + +/** + Check whether this Menu Option could be highlighted. + + This is an internal function. + + @param MenuOption The MenuOption to be checked. + + @retval TRUE This Menu Option is selectable. + @retval FALSE This Menu Option could not be selected. + +**/ +BOOLEAN +IsSelectable ( + UI_MENU_OPTION *MenuOption + ) +{ + if ((MenuOption->ThisTag->Operand == EFI_IFR_SUBTITLE_OP) || + MenuOption->GrayOut || MenuOption->ReadOnly) { + return FALSE; + } else { + return TRUE; + } +} + + +/** + Determine if the menu is the last menu that can be selected. + + This is an internal function. + + @param Direction The scroll direction. False is down. True is up. + @param CurrentPos The current focus. + + @return FALSE -- the menu isn't the last menu that can be selected. + @return TRUE -- the menu is the last menu that can be selected. + +**/ +BOOLEAN +ValueIsScroll ( + IN BOOLEAN Direction, + IN LIST_ENTRY *CurrentPos + ) +{ + LIST_ENTRY *Temp; + + Temp = Direction ? CurrentPos->BackLink : CurrentPos->ForwardLink; + + if (Temp == &gMenuOption) { + return TRUE; + } + + return FALSE; +} + + +/** + Move to next selectable statement. + + This is an internal function. + + @param Selection Menu selection. + @param GoUp The navigation direction. TRUE: up, FALSE: down. + @param CurrentPosition Current position. + @param GapToTop Gap position to top or bottom. + + @return The row distance from current MenuOption to next selectable MenuOption. + + @retval -1 Reach the begin of the menu, still can't find the selectable menu. + @retval Value Find the selectable menu, maybe the truly selectable, maybe the l + last menu showing at current form. + +**/ +INTN +MoveToNextStatement ( + IN UI_MENU_SELECTION *Selection, + IN BOOLEAN GoUp, + IN OUT LIST_ENTRY **CurrentPosition, + IN UINTN GapToTop + ) +{ + INTN Distance; + LIST_ENTRY *Pos; + UI_MENU_OPTION *NextMenuOption; + UI_MENU_OPTION *PreMenuOption; + + Distance = 0; + Pos = *CurrentPosition; + PreMenuOption = MENU_OPTION_FROM_LINK (Pos); + + while (TRUE) { + NextMenuOption = MENU_OPTION_FROM_LINK (Pos); + // + // NextMenuOption->Row == 0 means this menu has not calculate + // the NextMenuOption->Skip value yet, just calculate here. + // + if (NextMenuOption->Row == 0) { + UpdateOptionSkipLines (Selection, NextMenuOption); + } + + if (GoUp && (PreMenuOption != NextMenuOption)) { + // + // In this case, still can't find the selectable menu, + // return the last one in the showing form. + // + if ((UINTN) Distance + NextMenuOption->Skip > GapToTop) { + NextMenuOption = PreMenuOption; + break; + } + + // + // Current Position doesn't need to be caculated when go up. + // Caculate distanct at first when go up + // + Distance += NextMenuOption->Skip; + } + + if (IsSelectable (NextMenuOption)) { + break; + } + + // + // Arrive at begin of the menu list. + // + if ((GoUp ? Pos->BackLink : Pos->ForwardLink) == &gMenuOption) { + Distance = -1; + break; + } + + if (!GoUp) { + // + // In this case, still can't find the selectable menu, + // return the last one in the showing form. + // + if ((UINTN) Distance + NextMenuOption->Skip > GapToTop) { + NextMenuOption = PreMenuOption; + break; + } + + Distance += NextMenuOption->Skip; + } + + PreMenuOption = NextMenuOption; + Pos = (GoUp ? Pos->BackLink : Pos->ForwardLink); + } + + *CurrentPosition = &NextMenuOption->Link; + return Distance; +} + + +/** + Adjust Data and Time position accordingly. + Data format : [01/02/2004] [11:22:33] + Line number : 0 0 1 0 0 1 + + This is an internal function. + + @param DirectionUp the up or down direction. False is down. True is + up. + @param CurrentPosition Current position. On return: Point to the last + Option (Year or Second) if up; Point to the first + Option (Month or Hour) if down. + + @return Return line number to pad. It is possible that we stand on a zero-advance + @return data or time opcode, so pad one line when we judge if we are going to scroll outside. + +**/ +UINTN +AdjustDateAndTimePosition ( + IN BOOLEAN DirectionUp, + IN OUT LIST_ENTRY **CurrentPosition + ) +{ + UINTN Count; + LIST_ENTRY *NewPosition; + UI_MENU_OPTION *MenuOption; + UINTN PadLineNumber; + + PadLineNumber = 0; + NewPosition = *CurrentPosition; + MenuOption = MENU_OPTION_FROM_LINK (NewPosition); + + if ((MenuOption->ThisTag->Operand == EFI_IFR_DATE_OP) || + (MenuOption->ThisTag->Operand == EFI_IFR_TIME_OP)) { + // + // Calculate the distance from current position to the last Date/Time MenuOption + // + Count = 0; + while (MenuOption->Skip == 0) { + Count++; + NewPosition = NewPosition->ForwardLink; + MenuOption = MENU_OPTION_FROM_LINK (NewPosition); + PadLineNumber = 1; + } + + NewPosition = *CurrentPosition; + if (DirectionUp) { + // + // Since the behavior of hitting the up arrow on a Date/Time MenuOption is intended + // to be one that back to the previous set of MenuOptions, we need to advance to the first + // Date/Time MenuOption and leave the remaining logic in CfUiUp intact so the appropriate + // checking can be done. + // + while (Count++ < 2) { + NewPosition = NewPosition->BackLink; + } + } else { + // + // Since the behavior of hitting the down arrow on a Date/Time MenuOption is intended + // to be one that progresses to the next set of MenuOptions, we need to advance to the last + // Date/Time MenuOption and leave the remaining logic in CfUiDown intact so the appropriate + // checking can be done. + // + while (Count-- > 0) { + NewPosition = NewPosition->ForwardLink; + } + } + + *CurrentPosition = NewPosition; + } + + return PadLineNumber; +} + +/** + Find HII Handle in the HII database associated with given Device Path. + + If DevicePath is NULL, then ASSERT. + + @param DevicePath Device Path associated with the HII package list + handle. + + @retval Handle HII package list Handle associated with the Device + Path. + @retval NULL Hii Package list handle is not found. + +**/ +EFI_HII_HANDLE +EFIAPI +DevicePathToHiiHandle ( + IN EFI_DEVICE_PATH_PROTOCOL *DevicePath + ) +{ + EFI_STATUS Status; + EFI_DEVICE_PATH_PROTOCOL *TmpDevicePath; + UINTN BufferSize; + UINTN HandleCount; + UINTN Index; + EFI_HANDLE Handle; + EFI_HANDLE DriverHandle; + EFI_HII_HANDLE *HiiHandles; + EFI_HII_HANDLE HiiHandle; + + ASSERT (DevicePath != NULL); + + TmpDevicePath = DevicePath; + // + // Locate Device Path Protocol handle buffer + // + Status = gBS->LocateDevicePath ( + &gEfiDevicePathProtocolGuid, + &TmpDevicePath, + &DriverHandle + ); + if (EFI_ERROR (Status) || !IsDevicePathEnd (TmpDevicePath)) { + return NULL; + } + + // + // Retrieve all HII Handles from HII database + // + BufferSize = 0x1000; + HiiHandles = AllocatePool (BufferSize); + ASSERT (HiiHandles != NULL); + Status = mHiiDatabase->ListPackageLists ( + mHiiDatabase, + EFI_HII_PACKAGE_TYPE_ALL, + NULL, + &BufferSize, + HiiHandles + ); + if (Status == EFI_BUFFER_TOO_SMALL) { + FreePool (HiiHandles); + HiiHandles = AllocatePool (BufferSize); + ASSERT (HiiHandles != NULL); + + Status = mHiiDatabase->ListPackageLists ( + mHiiDatabase, + EFI_HII_PACKAGE_TYPE_ALL, + NULL, + &BufferSize, + HiiHandles + ); + } + + if (EFI_ERROR (Status)) { + FreePool (HiiHandles); + return NULL; + } + + // + // Search Hii Handle by Driver Handle + // + HiiHandle = NULL; + HandleCount = BufferSize / sizeof (EFI_HII_HANDLE); + for (Index = 0; Index < HandleCount; Index++) { + Status = mHiiDatabase->GetPackageListHandle ( + mHiiDatabase, + HiiHandles[Index], + &Handle + ); + if (!EFI_ERROR (Status) && (Handle == DriverHandle)) { + HiiHandle = HiiHandles[Index]; + break; + } + } + + FreePool (HiiHandles); + return HiiHandle; +} + +/** + Find HII Handle in the HII database associated with given form set guid. + + If FormSetGuid is NULL, then ASSERT. + + @param ComparingGuid FormSet Guid associated with the HII package list + handle. + + @retval Handle HII package list Handle associated with the Device + Path. + @retval NULL Hii Package list handle is not found. + +**/ +EFI_HII_HANDLE +FormSetGuidToHiiHandle ( + EFI_GUID *ComparingGuid + ) +{ + EFI_HII_HANDLE *HiiHandles; + UINTN Index; + EFI_HII_PACKAGE_LIST_HEADER *HiiPackageList; + UINTN BufferSize; + UINT32 Offset; + UINT32 Offset2; + UINT32 PackageListLength; + EFI_HII_PACKAGE_HEADER PackageHeader; + UINT8 *Package; + UINT8 *OpCodeData; + EFI_STATUS Status; + EFI_HII_HANDLE HiiHandle; + + ASSERT (ComparingGuid != NULL); + + HiiHandle = NULL; + // + // Get all the Hii handles + // + HiiHandles = HiiGetHiiHandles (NULL); + ASSERT (HiiHandles != NULL); + + // + // Search for formset of each class type + // + for (Index = 0; HiiHandles[Index] != NULL; Index++) { + BufferSize = 0; + HiiPackageList = NULL; + Status = mHiiDatabase->ExportPackageLists (mHiiDatabase, HiiHandles[Index], &BufferSize, HiiPackageList); + if (Status == EFI_BUFFER_TOO_SMALL) { + HiiPackageList = AllocatePool (BufferSize); + ASSERT (HiiPackageList != NULL); + + Status = mHiiDatabase->ExportPackageLists (mHiiDatabase, HiiHandles[Index], &BufferSize, HiiPackageList); + } + if (EFI_ERROR (Status) || HiiPackageList == NULL) { + return NULL; + } + + // + // Get Form package from this HII package List + // + Offset = sizeof (EFI_HII_PACKAGE_LIST_HEADER); + Offset2 = 0; + CopyMem (&PackageListLength, &HiiPackageList->PackageLength, sizeof (UINT32)); + + while (Offset < PackageListLength) { + Package = ((UINT8 *) HiiPackageList) + Offset; + CopyMem (&PackageHeader, Package, sizeof (EFI_HII_PACKAGE_HEADER)); + + if (PackageHeader.Type == EFI_HII_PACKAGE_FORMS) { + // + // Search FormSet in this Form Package + // + Offset2 = sizeof (EFI_HII_PACKAGE_HEADER); + while (Offset2 < PackageHeader.Length) { + OpCodeData = Package + Offset2; + + if (((EFI_IFR_OP_HEADER *) OpCodeData)->OpCode == EFI_IFR_FORM_SET_OP) { + // + // Try to compare against formset GUID + // + if (CompareGuid (ComparingGuid, (EFI_GUID *)(OpCodeData + sizeof (EFI_IFR_OP_HEADER)))) { + HiiHandle = HiiHandles[Index]; + break; + } + } + + Offset2 += ((EFI_IFR_OP_HEADER *) OpCodeData)->Length; + } + } + if (HiiHandle != NULL) { + break; + } + Offset += PackageHeader.Length; + } + + FreePool (HiiPackageList); + if (HiiHandle != NULL) { + break; + } + } + + FreePool (HiiHandles); + + return HiiHandle; +} + +/** + Process the goto op code, update the info in the selection structure. + + @param Statement The statement belong to goto op code. + @param Selection The selection info. + @param Repaint Whether need to repaint the menu. + @param NewLine Whether need to create new line. + + @retval EFI_SUCCESS The menu process successfully. + @return Other value if the process failed. +**/ +EFI_STATUS +ProcessGotoOpCode ( + IN OUT FORM_BROWSER_STATEMENT *Statement, + IN OUT UI_MENU_SELECTION *Selection, + OUT BOOLEAN *Repaint, + OUT BOOLEAN *NewLine + ) +{ + CHAR16 *StringPtr; + EFI_DEVICE_PATH_PROTOCOL *DevicePath; + FORM_BROWSER_FORM *RefForm; + EFI_INPUT_KEY Key; + EFI_STATUS Status; + + Status = EFI_SUCCESS; + StringPtr = NULL; + + // + // Prepare the device path check, get the device path info first. + // + if (Statement->HiiValue.Value.ref.DevicePath != 0) { + StringPtr = GetToken (Statement->HiiValue.Value.ref.DevicePath, Selection->FormSet->HiiHandle); + } + + // + // Check whether the device path string is a valid string. + // + if (Statement->HiiValue.Value.ref.DevicePath != 0 && StringPtr != NULL) { + if (Selection->Form->ModalForm) { + return Status; + } + + // + // Goto another Hii Package list + // + if (mPathFromText != NULL) { + DevicePath = mPathFromText->ConvertTextToDevicePath(StringPtr); + if (DevicePath != NULL) { + Selection->Handle = DevicePathToHiiHandle (DevicePath); + FreePool (DevicePath); + } + FreePool (StringPtr); + } else { + // + // Not found the EFI_DEVICE_PATH_FROM_TEXT_PROTOCOL protocol. + // + do { + CreateDialog (4, TRUE, 0, NULL, &Key, gEmptyString, gProtocolNotFound, gPressEnter, gEmptyString); + } while (Key.UnicodeChar != CHAR_CARRIAGE_RETURN); + if (Repaint != NULL) { + *Repaint = TRUE; + } + FreePool (StringPtr); + return Status; + } + + Selection->Action = UI_ACTION_REFRESH_FORMSET; + if (Selection->Handle == NULL) { + // + // If target Hii Handle not found, exit + // + Selection->Action = UI_ACTION_EXIT; + Selection->Statement = NULL; + return Status; + } + + CopyMem (&Selection->FormSetGuid,&Statement->HiiValue.Value.ref.FormSetGuid, sizeof (EFI_GUID)); + Selection->FormId = Statement->HiiValue.Value.ref.FormId; + Selection->QuestionId = Statement->HiiValue.Value.ref.QuestionId; + } else if (!CompareGuid (&Statement->HiiValue.Value.ref.FormSetGuid, &gZeroGuid)) { + if (Selection->Form->ModalForm) { + return Status; + } + // + // Goto another Formset, check for uncommitted data + // + Selection->Action = UI_ACTION_REFRESH_FORMSET; + + Selection->Handle = FormSetGuidToHiiHandle(&Statement->HiiValue.Value.ref.FormSetGuid); + if (Selection->Handle == NULL) { + // + // If target Hii Handle not found, exit + // + Selection->Action = UI_ACTION_EXIT; + Selection->Statement = NULL; + return Status; + } + + CopyMem (&Selection->FormSetGuid, &Statement->HiiValue.Value.ref.FormSetGuid, sizeof (EFI_GUID)); + Selection->FormId = Statement->HiiValue.Value.ref.FormId; + Selection->QuestionId = Statement->HiiValue.Value.ref.QuestionId; + } else if (Statement->HiiValue.Value.ref.FormId != 0) { + // + // Check whether target From is suppressed. + // + RefForm = IdToForm (Selection->FormSet, Statement->HiiValue.Value.ref.FormId); + + if ((RefForm != NULL) && (RefForm->SuppressExpression != NULL)) { + if (EvaluateExpressionList(RefForm->SuppressExpression, TRUE, Selection->FormSet, RefForm) != ExpressFalse) { + // + // Form is suppressed. + // + do { + CreateDialog (4, TRUE, 0, NULL, &Key, gEmptyString, gFormSuppress, gPressEnter, gEmptyString); + } while (Key.UnicodeChar != CHAR_CARRIAGE_RETURN); + if (Repaint != NULL) { + *Repaint = TRUE; + } + return Status; + } + } + + // + // Goto another form inside this formset, + // + Selection->Action = UI_ACTION_REFRESH_FORM; + + Selection->FormId = Statement->HiiValue.Value.ref.FormId; + Selection->QuestionId = Statement->HiiValue.Value.ref.QuestionId; + } else if (Statement->HiiValue.Value.ref.QuestionId != 0) { + // + // Goto another Question + // + Selection->QuestionId = Statement->HiiValue.Value.ref.QuestionId; + + if ((Statement->QuestionFlags & EFI_IFR_FLAG_CALLBACK) != 0) { + Selection->Action = UI_ACTION_REFRESH_FORM; + } else { + if (Repaint != NULL) { + *Repaint = TRUE; + } + if (NewLine != NULL) { + *NewLine = TRUE; + } + } + } else { + if ((Statement->QuestionFlags & EFI_IFR_FLAG_CALLBACK) != 0) { + Selection->Action = UI_ACTION_REFRESH_FORM; + } + } + + return Status; +} + +/** + Display menu and wait for user to select one menu option, then return it. + If AutoBoot is enabled, then if user doesn't select any option, + after period of time, it will automatically return the first menu option. + + @param Selection Menu selection. + + @retval EFI_SUCESSS This function always return successfully for now. + +**/ +EFI_STATUS +UiDisplayMenu ( + IN OUT UI_MENU_SELECTION *Selection + ) +{ + INTN SkipValue; + INTN Difference; + UINTN DistanceValue; + UINTN Row; + UINTN Col; + UINTN Temp; + UINTN Temp2; + UINTN TopRow; + UINTN BottomRow; + UINTN OriginalRow; + UINTN Index; + UINT16 Width; + CHAR16 *StringPtr; + CHAR16 *OptionString; + CHAR16 *OutputString; + CHAR16 *HelpString; + CHAR16 *HelpHeaderString; + CHAR16 *HelpBottomString; + BOOLEAN NewLine; + BOOLEAN Repaint; + BOOLEAN SavedValue; + BOOLEAN UpArrow; + BOOLEAN DownArrow; + BOOLEAN InitializedFlag; + EFI_STATUS Status; + EFI_INPUT_KEY Key; + LIST_ENTRY *Link; + LIST_ENTRY *NewPos; + LIST_ENTRY *TopOfScreen; + LIST_ENTRY *SavedListEntry; + UI_MENU_OPTION *MenuOption; + UI_MENU_OPTION *NextMenuOption; + UI_MENU_OPTION *SavedMenuOption; + UI_MENU_OPTION *PreviousMenuOption; + UI_CONTROL_FLAG ControlFlag; + EFI_SCREEN_DESCRIPTOR LocalScreen; + MENU_REFRESH_ENTRY *MenuRefreshEntry; + MENU_REFRESH_ENTRY *MenuUpdateEntry; + UI_SCREEN_OPERATION ScreenOperation; + UINT8 MinRefreshInterval; + UINT16 DefaultId; + FORM_BROWSER_STATEMENT *Statement; + UI_MENU_LIST *CurrentMenu; + UINTN ModalSkipColumn; + BROWSER_HOT_KEY *HotKey; + UINTN HelpPageIndex; + UINTN HelpPageCount; + UINTN RowCount; + UINTN HelpLine; + UINTN HelpHeaderLine; + UINTN HelpBottomLine; + BOOLEAN MultiHelpPage; + UINT16 GlyphWidth; + UINT16 EachLineWidth; + UINT16 HeaderLineWidth; + UINT16 BottomLineWidth; + + CopyMem (&LocalScreen, &gScreenDimensions, sizeof (EFI_SCREEN_DESCRIPTOR)); + + Status = EFI_SUCCESS; + HelpString = NULL; + HelpHeaderString = NULL; + HelpBottomString = NULL; + OptionString = NULL; + ScreenOperation = UiNoOperation; + NewLine = TRUE; + MinRefreshInterval = 0; + DefaultId = 0; + HelpPageCount = 0; + HelpLine = 0; + RowCount = 0; + HelpBottomLine = 0; + HelpHeaderLine = 0; + HelpPageIndex = 0; + MultiHelpPage = FALSE; + EachLineWidth = 0; + HeaderLineWidth = 0; + BottomLineWidth = 0; + OutputString = NULL; + UpArrow = FALSE; + DownArrow = FALSE; + SkipValue = 0; + MenuRefreshEntry = gMenuRefreshHead; + + NextMenuOption = NULL; + PreviousMenuOption = NULL; + SavedMenuOption = NULL; + HotKey = NULL; + ModalSkipColumn = (LocalScreen.RightColumn - LocalScreen.LeftColumn) / 6; + + ZeroMem (&Key, sizeof (EFI_INPUT_KEY)); + + if ((gClassOfVfr & FORMSET_CLASS_FRONT_PAGE) == FORMSET_CLASS_FRONT_PAGE){ + TopRow = LocalScreen.TopRow + FRONT_PAGE_HEADER_HEIGHT + SCROLL_ARROW_HEIGHT; + Row = LocalScreen.TopRow + FRONT_PAGE_HEADER_HEIGHT + SCROLL_ARROW_HEIGHT; + } else { + TopRow = LocalScreen.TopRow + NONE_FRONT_PAGE_HEADER_HEIGHT + SCROLL_ARROW_HEIGHT; + Row = LocalScreen.TopRow + NONE_FRONT_PAGE_HEADER_HEIGHT + SCROLL_ARROW_HEIGHT; + } + + if (Selection->Form->ModalForm) { + Col = LocalScreen.LeftColumn + LEFT_SKIPPED_COLUMNS + ModalSkipColumn; + } else { + Col = LocalScreen.LeftColumn + LEFT_SKIPPED_COLUMNS; + } + + BottomRow = LocalScreen.BottomRow - STATUS_BAR_HEIGHT - gFooterHeight - SCROLL_ARROW_HEIGHT - 1; + + Selection->TopRow = TopRow; + Selection->BottomRow = BottomRow; + Selection->PromptCol = Col; + Selection->OptionCol = gPromptBlockWidth + 1 + LocalScreen.LeftColumn; + Selection->Statement = NULL; + + TopOfScreen = gMenuOption.ForwardLink; + Repaint = TRUE; + MenuOption = NULL; + + // + // Find current Menu + // + CurrentMenu = UiFindMenuList (Selection->Handle, &Selection->FormSetGuid, Selection->FormId); + if (CurrentMenu == NULL) { + // + // Current menu not found, add it to the menu tree + // + CurrentMenu = UiAddMenuList (Selection->CurrentMenu, Selection->Handle, &Selection->FormSetGuid, Selection->FormId); + } + ASSERT (CurrentMenu != NULL); + Selection->CurrentMenu = CurrentMenu; + + if (Selection->QuestionId == 0) { + // + // Highlight not specified, fetch it from cached menu + // + Selection->QuestionId = CurrentMenu->QuestionId; + Selection->Sequence = CurrentMenu->Sequence; + } + + // + // Init option as the current user's selection + // + InitializedFlag = TRUE; + NewPos = gMenuOption.ForwardLink; + + gST->ConOut->EnableCursor (gST->ConOut, FALSE); + UpdateStatusBar (Selection, REFRESH_STATUS_BAR, (UINT8) 0, TRUE); + + ControlFlag = CfInitialization; + Selection->Action = UI_ACTION_NONE; + while (TRUE) { + switch (ControlFlag) { + case CfInitialization: + if (IsListEmpty (&gMenuOption)) { + ControlFlag = CfReadKey; + } else { + ControlFlag = CfCheckSelection; + } + break; + + case CfCheckSelection: + if (Selection->Action != UI_ACTION_NONE) { + ControlFlag = CfExit; + } else { + ControlFlag = CfRepaint; + } + break; + + case CfRepaint: + ControlFlag = CfRefreshHighLight; + + if (Repaint) { + // + // Display menu + // + DownArrow = FALSE; + UpArrow = FALSE; + Row = TopRow; + + Temp = (UINTN) SkipValue; + Temp2 = (UINTN) SkipValue; + + // + // 1. Clear the screen. + // + if (Selection->Form->ModalForm) { + ClearLines ( + LocalScreen.LeftColumn + ModalSkipColumn, + LocalScreen.LeftColumn + ModalSkipColumn + gPromptBlockWidth + gOptionBlockWidth, + TopRow - SCROLL_ARROW_HEIGHT, + BottomRow + SCROLL_ARROW_HEIGHT, + PcdGet8 (PcdBrowserFieldTextColor) | FIELD_BACKGROUND + ); + } else { + ClearLines ( + LocalScreen.LeftColumn, + LocalScreen.RightColumn, + TopRow - SCROLL_ARROW_HEIGHT, + BottomRow + SCROLL_ARROW_HEIGHT, + PcdGet8 (PcdBrowserFieldTextColor) | FIELD_BACKGROUND + ); + } + UiFreeRefreshList (); + MinRefreshInterval = 0; + + // + // 2.Paint the menu. + // + for (Link = TopOfScreen; Link != &gMenuOption; Link = Link->ForwardLink) { + MenuOption = MENU_OPTION_FROM_LINK (Link); + MenuOption->Row = Row; + MenuOption->Col = Col; + if (Selection->Form->ModalForm) { + MenuOption->OptCol = gPromptBlockWidth + 1 + LocalScreen.LeftColumn + ModalSkipColumn; + } else { + MenuOption->OptCol = gPromptBlockWidth + 1 + LocalScreen.LeftColumn; + } + + Statement = MenuOption->ThisTag; + if (Statement->InSubtitle) { + MenuOption->Col += SUBTITLE_INDENT; + } + + if (MenuOption->GrayOut) { + gST->ConOut->SetAttribute (gST->ConOut, FIELD_TEXT_GRAYED | FIELD_BACKGROUND); + } else { + if (Statement->Operand == EFI_IFR_SUBTITLE_OP) { + gST->ConOut->SetAttribute (gST->ConOut, PcdGet8 (PcdBrowserSubtitleTextColor) | FIELD_BACKGROUND); + } + } + + Width = GetWidth (Statement, MenuOption->Handle); + OriginalRow = Row; + GlyphWidth = 1; + + if (Statement->Operand == EFI_IFR_REF_OP && MenuOption->Col >= 2) { + // + // Print Arrow for Goto button. + // + PrintAt ( + MenuOption->Col - 2, + Row, + L"%c", + GEOMETRICSHAPE_RIGHT_TRIANGLE + ); + } + + // + // 2.1. Paint the description. + // + for (Index = 0; GetLineByWidth (MenuOption->Description, Width, &GlyphWidth, &Index, &OutputString) != 0x0000;) { + // + // Temp means need to skip how many lines from the start. + // + if ((Temp == 0) && (Row <= BottomRow)) { + PrintStringAt (MenuOption->Col, Row, OutputString); + } + // + // If there is more string to process print on the next row and increment the Skip value + // + if (StrLen (&MenuOption->Description[Index]) != 0) { + if (Temp == 0) { + Row++; + } + } + + FreePool (OutputString); + if (Temp != 0) { + Temp--; + } + } + + Temp = 0; + Row = OriginalRow; + + // + // 2.2. Paint the option string. + // + Status = ProcessOptions (Selection, MenuOption, FALSE, &OptionString); + if (EFI_ERROR (Status)) { + // + // Repaint to clear possible error prompt pop-up + // + Repaint = TRUE; + NewLine = TRUE; + ControlFlag = CfRepaint; + break; + } + + if (OptionString != NULL) { + if (Statement->Operand == EFI_IFR_DATE_OP || Statement->Operand == EFI_IFR_TIME_OP) { + ProcessStringForDateTime(MenuOption, OptionString, TRUE); + } + + Width = (UINT16) gOptionBlockWidth; + OriginalRow = Row; + GlyphWidth = 1; + + for (Index = 0; GetLineByWidth (OptionString, Width, &GlyphWidth, &Index, &OutputString) != 0x0000;) { + if ((Temp2 == 0) && (Row <= BottomRow)) { + PrintStringAt (MenuOption->OptCol, Row, OutputString); + } + // + // If there is more string to process print on the next row and increment the Skip value + // + if (StrLen (&OptionString[Index]) != 0) { + if (Temp2 == 0) { + Row++; + // + // Since the Number of lines for this menu entry may or may not be reflected accurately + // since the prompt might be 1 lines and option might be many, and vice versa, we need to do + // some testing to ensure we are keeping this in-sync. + // + // If the difference in rows is greater than or equal to the skip value, increase the skip value + // + if ((Row - OriginalRow) >= MenuOption->Skip) { + MenuOption->Skip++; + } + } + } + + FreePool (OutputString); + if (Temp2 != 0) { + Temp2--; + } + } + + Temp2 = 0; + Row = OriginalRow; + + FreePool (OptionString); + } + + // + // 2.4 Special process for Test opcode with test two. + // + if (!CompareGuid (&Statement->RefreshGuid, &gZeroGuid)) { + if (gMenuEventGuidRefreshHead == NULL) { + MenuUpdateEntry = AllocateZeroPool (sizeof (MENU_REFRESH_ENTRY)); + gMenuEventGuidRefreshHead = MenuUpdateEntry; + } else { + MenuUpdateEntry = gMenuEventGuidRefreshHead; + while (MenuUpdateEntry->Next != NULL) { + MenuUpdateEntry = MenuUpdateEntry->Next; + } + MenuUpdateEntry->Next = AllocateZeroPool (sizeof (MENU_REFRESH_ENTRY)); + MenuUpdateEntry = MenuUpdateEntry->Next; + } + ASSERT (MenuUpdateEntry != NULL); + Status = gBS->CreateEventEx (EVT_NOTIFY_SIGNAL, TPL_NOTIFY, RefreshQuestionNotify, MenuUpdateEntry, &Statement->RefreshGuid, &MenuUpdateEntry->Event); + ASSERT (!EFI_ERROR (Status)); + MenuUpdateEntry->MenuOption = MenuOption; + MenuUpdateEntry->Selection = Selection; + MenuUpdateEntry->CurrentColumn = MenuOption->OptCol; + MenuUpdateEntry->CurrentRow = MenuOption->Row; + if (MenuOption->GrayOut) { + MenuUpdateEntry->CurrentAttribute = FIELD_TEXT_GRAYED | FIELD_BACKGROUND; + } else { + MenuUpdateEntry->CurrentAttribute = PcdGet8 (PcdBrowserFieldTextColor) | FIELD_BACKGROUND; + } + } + + // + // If Question request refresh, register the op-code + // + if (Statement->RefreshInterval != 0) { + // + // Menu will be refreshed at minimal interval of all Questions + // which have refresh request + // + if (MinRefreshInterval == 0 || Statement->RefreshInterval < MinRefreshInterval) { + MinRefreshInterval = Statement->RefreshInterval; + } + + if (gMenuRefreshHead == NULL) { + MenuRefreshEntry = AllocateZeroPool (sizeof (MENU_REFRESH_ENTRY)); + gMenuRefreshHead = MenuRefreshEntry; + } else { + MenuRefreshEntry = gMenuRefreshHead; + while (MenuRefreshEntry->Next != NULL) { + MenuRefreshEntry = MenuRefreshEntry->Next; + } + MenuRefreshEntry->Next = AllocateZeroPool (sizeof (MENU_REFRESH_ENTRY)); + MenuRefreshEntry = MenuRefreshEntry->Next; + } + ASSERT (MenuRefreshEntry != NULL); + MenuRefreshEntry->MenuOption = MenuOption; + MenuRefreshEntry->Selection = Selection; + MenuRefreshEntry->CurrentColumn = MenuOption->OptCol; + MenuRefreshEntry->CurrentRow = MenuOption->Row; + if (MenuOption->GrayOut) { + MenuRefreshEntry->CurrentAttribute = FIELD_TEXT_GRAYED | FIELD_BACKGROUND; + } else { + MenuRefreshEntry->CurrentAttribute = PcdGet8 (PcdBrowserFieldTextColor) | FIELD_BACKGROUND; + } + } + + // + // If this is a text op with secondary text information + // + if ((Statement->Operand == EFI_IFR_TEXT_OP) && (Statement->TextTwo != 0)) { + StringPtr = GetToken (Statement->TextTwo, MenuOption->Handle); + + Width = (UINT16) gOptionBlockWidth; + OriginalRow = Row; + GlyphWidth = 1; + + for (Index = 0; GetLineByWidth (StringPtr, Width, &GlyphWidth, &Index, &OutputString) != 0x0000;) { + if ((Temp == 0) && (Row <= BottomRow)) { + PrintStringAt (MenuOption->OptCol, Row, OutputString); + } + // + // If there is more string to process print on the next row and increment the Skip value + // + if (StrLen (&StringPtr[Index]) != 0) { + if (Temp2 == 0) { + Row++; + // + // Since the Number of lines for this menu entry may or may not be reflected accurately + // since the prompt might be 1 lines and option might be many, and vice versa, we need to do + // some testing to ensure we are keeping this in-sync. + // + // If the difference in rows is greater than or equal to the skip value, increase the skip value + // + if ((Row - OriginalRow) >= MenuOption->Skip) { + MenuOption->Skip++; + } + } + } + + FreePool (OutputString); + if (Temp2 != 0) { + Temp2--; + } + } + + Row = OriginalRow; + FreePool (StringPtr); + } + gST->ConOut->SetAttribute (gST->ConOut, PcdGet8 (PcdBrowserFieldTextColor) | FIELD_BACKGROUND); + + // + // 3. Update the row info which will be used by next menu. + // + if (Link == TopOfScreen) { + Row += MenuOption->Skip - SkipValue; + } else { + Row += MenuOption->Skip; + } + + if (Row > BottomRow) { + if (!ValueIsScroll (FALSE, Link)) { + DownArrow = TRUE; + } + + Row = BottomRow + 1; + break; + } + } + + if (!ValueIsScroll (TRUE, TopOfScreen)) { + UpArrow = TRUE; + } + + if (UpArrow) { + gST->ConOut->SetAttribute (gST->ConOut, ARROW_TEXT | ARROW_BACKGROUND); + PrintAt ( + LocalScreen.LeftColumn + gPromptBlockWidth + gOptionBlockWidth + 1, + TopRow - SCROLL_ARROW_HEIGHT, + L"%c", + ARROW_UP + ); + gST->ConOut->SetAttribute (gST->ConOut, PcdGet8 (PcdBrowserFieldTextColor) | FIELD_BACKGROUND); + } + + if (DownArrow) { + gST->ConOut->SetAttribute (gST->ConOut, ARROW_TEXT | ARROW_BACKGROUND); + PrintAt ( + LocalScreen.LeftColumn + gPromptBlockWidth + gOptionBlockWidth + 1, + BottomRow + SCROLL_ARROW_HEIGHT, + L"%c", + ARROW_DOWN + ); + gST->ConOut->SetAttribute (gST->ConOut, PcdGet8 (PcdBrowserFieldTextColor) | FIELD_BACKGROUND); + } + + MenuOption = NULL; + } + break; + + case CfRefreshHighLight: + // + // MenuOption: Last menu option that need to remove hilight + // MenuOption is set to NULL in Repaint + // NewPos: Current menu option that need to hilight + // + ControlFlag = CfUpdateHelpString; + if (TopOfScreen == &MenuOption->Link) { + Temp = SkipValue; + } else { + Temp = 0; + } + if (NewPos == TopOfScreen) { + Temp2 = SkipValue; + } else { + Temp2 = 0; + } + if (InitializedFlag) { + InitializedFlag = FALSE; + MoveToNextStatement (Selection, FALSE, &NewPos, BottomRow - TopRow); + } + + // + // Repaint flag is normally reset when finish processing CfUpdateHelpString. Temporarily + // reset Repaint flag because we may break halfway and skip CfUpdateHelpString processing. + // + SavedValue = Repaint; + Repaint = FALSE; + + if (Selection->QuestionId != 0) { + NewPos = gMenuOption.ForwardLink; + SavedMenuOption = MENU_OPTION_FROM_LINK (NewPos); + + while ((SavedMenuOption->ThisTag->QuestionId != Selection->QuestionId || + SavedMenuOption->Sequence != Selection->Sequence) && + NewPos->ForwardLink != &gMenuOption) { + NewPos = NewPos->ForwardLink; + SavedMenuOption = MENU_OPTION_FROM_LINK (NewPos); + } + if (SavedMenuOption->ThisTag->QuestionId == Selection->QuestionId) { + // + // Target Question found, find its MenuOption + // + Link = TopOfScreen; + + for (Index = TopRow; Index <= BottomRow && Link != NewPos;) { + SavedMenuOption = MENU_OPTION_FROM_LINK (Link); + Index += SavedMenuOption->Skip; + if (Link == TopOfScreen) { + Index -= SkipValue; + } + Link = Link->ForwardLink; + } + if (NewPos == Link) { + SavedMenuOption = MENU_OPTION_FROM_LINK (Link); + } + + // + // Not find the selected menu in current show page. + // Have two case to enter this if: + // 1. Not find the menu at current page. + // 2. Find the menu in current page, but the menu shows at the bottom and not all info shows. + // For case 2, has an exception: The menu can show more than one pages and now only this menu shows. + // + // Base on the selected menu will show at the bottom of the page, + // select the menu which will show at the top of the page. + // + if (Link != NewPos || Index > BottomRow || + (Link == NewPos && (SavedMenuOption->Row + SavedMenuOption->Skip - 1 > BottomRow) && (Link != TopOfScreen))) { + // + // Find the MenuOption which has the skip value for Date/Time opcode. + // + AdjustDateAndTimePosition(FALSE, &NewPos); + // + // NewPos is not in the current page, simply scroll page so that NewPos is in the end of the page + // + SavedMenuOption = MENU_OPTION_FROM_LINK (NewPos); + // + // SavedMenuOption->Row == 0 means the menu not show yet. + // + if (SavedMenuOption->Row == 0) { + UpdateOptionSkipLines (Selection, SavedMenuOption); + } + + // + // Base on the selected menu will show at the bottome of next page, + // select the menu show at the top of the next page. + // + Link = NewPos; + for (Index = TopRow + SavedMenuOption->Skip; Index <= BottomRow + 1; ) { + Link = Link->BackLink; + SavedMenuOption = MENU_OPTION_FROM_LINK (Link); + if (SavedMenuOption->Row == 0) { + UpdateOptionSkipLines (Selection, SavedMenuOption); + } + Index += SavedMenuOption->Skip; + } + + // + // Found the menu which will show at the top of the page. + // + if (Link == NewPos) { + // + // The menu can show more than one pages, just show the menu at the top of the page. + // + SkipValue = 0; + TopOfScreen = Link; + } else { + // + // Check whether need to skip some line for menu shows at the top of the page. + // + SkipValue = Index - BottomRow - 1; + if (SkipValue > 0 && SkipValue < (INTN) SavedMenuOption->Skip) { + TopOfScreen = Link; + } else { + SkipValue = 0; + TopOfScreen = Link->ForwardLink; + } + } + + Repaint = TRUE; + NewLine = TRUE; + ControlFlag = CfRepaint; + break; + } + } else { + // + // Target Question not found, highlight the default menu option + // + NewPos = TopOfScreen; + } + + Selection->QuestionId = 0; + } + + if (NewPos != NULL && (MenuOption == NULL || NewPos != &MenuOption->Link)) { + if (MenuOption != NULL) { + // + // Remove highlight on last Menu Option + // + gST->ConOut->SetCursorPosition (gST->ConOut, MenuOption->Col, MenuOption->Row); + ProcessOptions (Selection, MenuOption, FALSE, &OptionString); + gST->ConOut->SetAttribute (gST->ConOut, PcdGet8 (PcdBrowserFieldTextColor) | FIELD_BACKGROUND); + if (OptionString != NULL) { + if ((MenuOption->ThisTag->Operand == EFI_IFR_DATE_OP) || + (MenuOption->ThisTag->Operand == EFI_IFR_TIME_OP) + ) { + ProcessStringForDateTime(MenuOption, OptionString, FALSE); + } + + Width = (UINT16) gOptionBlockWidth; + OriginalRow = MenuOption->Row; + GlyphWidth = 1; + + for (Index = 0; GetLineByWidth (OptionString, Width, &GlyphWidth, &Index, &OutputString) != 0x0000;) { + if ((Temp == 0) && (MenuOption->Row >= TopRow) && (MenuOption->Row <= BottomRow)) { + PrintStringAt (MenuOption->OptCol, MenuOption->Row, OutputString); + } + // + // If there is more string to process print on the next row and increment the Skip value + // + if (StrLen (&OptionString[Index]) != 0) { + if (Temp == 0) { + MenuOption->Row++; + } + } + + FreePool (OutputString); + if (Temp != 0) { + Temp--; + } + } + + MenuOption->Row = OriginalRow; + + FreePool (OptionString); + } else { + if (NewLine) { + if (MenuOption->GrayOut) { + gST->ConOut->SetAttribute (gST->ConOut, FIELD_TEXT_GRAYED | FIELD_BACKGROUND); + } else if (MenuOption->ThisTag->Operand == EFI_IFR_SUBTITLE_OP) { + gST->ConOut->SetAttribute (gST->ConOut, PcdGet8 (PcdBrowserSubtitleTextColor) | FIELD_BACKGROUND); + } + + OriginalRow = MenuOption->Row; + Width = GetWidth (MenuOption->ThisTag, MenuOption->Handle); + GlyphWidth = 1; + + for (Index = 0; GetLineByWidth (MenuOption->Description, Width, &GlyphWidth, &Index, &OutputString) != 0x0000;) { + if ((Temp == 0) && (MenuOption->Row >= TopRow) && (MenuOption->Row <= BottomRow)) { + PrintStringAt (MenuOption->Col, MenuOption->Row, OutputString); + } + // + // If there is more string to process print on the next row and increment the Skip value + // + if (StrLen (&MenuOption->Description[Index]) != 0) { + if (Temp == 0) { + MenuOption->Row++; + } + } + + FreePool (OutputString); + if (Temp != 0) { + Temp--; + } + } + + MenuOption->Row = OriginalRow; + gST->ConOut->SetAttribute (gST->ConOut, PcdGet8 (PcdBrowserFieldTextColor) | FIELD_BACKGROUND); + } + } + } + + // + // This is the current selected statement + // + MenuOption = MENU_OPTION_FROM_LINK (NewPos); + Statement = MenuOption->ThisTag; + Selection->Statement = Statement; + if (!IsSelectable (MenuOption)) { + Repaint = SavedValue; + UpdateKeyHelp (Selection, MenuOption, FALSE); + break; + } + + // + // Record highlight for current menu + // + CurrentMenu->QuestionId = Statement->QuestionId; + CurrentMenu->Sequence = MenuOption->Sequence; + + // + // Set reverse attribute + // + gST->ConOut->SetAttribute (gST->ConOut, PcdGet8 (PcdBrowserFieldTextHighlightColor) | PcdGet8 (PcdBrowserFieldBackgroundHighlightColor)); + gST->ConOut->SetCursorPosition (gST->ConOut, MenuOption->Col, MenuOption->Row); + + // + // Assuming that we have a refresh linked-list created, lets annotate the + // appropriate entry that we are highlighting with its new attribute. Just prior to this + // lets reset all of the entries' attribute so we do not get multiple highlights in he refresh + // + if (gMenuRefreshHead != NULL) { + for (MenuRefreshEntry = gMenuRefreshHead; MenuRefreshEntry != NULL; MenuRefreshEntry = MenuRefreshEntry->Next) { + if (MenuRefreshEntry->MenuOption->GrayOut) { + MenuRefreshEntry->CurrentAttribute = FIELD_TEXT_GRAYED | FIELD_BACKGROUND; + } else { + MenuRefreshEntry->CurrentAttribute = PcdGet8 (PcdBrowserFieldTextColor) | FIELD_BACKGROUND; + } + if (MenuRefreshEntry->MenuOption == MenuOption) { + MenuRefreshEntry->CurrentAttribute = PcdGet8 (PcdBrowserFieldTextHighlightColor) | PcdGet8 (PcdBrowserFieldBackgroundHighlightColor); + } + } + } + + ProcessOptions (Selection, MenuOption, FALSE, &OptionString); + if (OptionString != NULL) { + if (Statement->Operand == EFI_IFR_DATE_OP || Statement->Operand == EFI_IFR_TIME_OP) { + ProcessStringForDateTime(MenuOption, OptionString, FALSE); + } + Width = (UINT16) gOptionBlockWidth; + + OriginalRow = MenuOption->Row; + GlyphWidth = 1; + + for (Index = 0; GetLineByWidth (OptionString, Width, &GlyphWidth, &Index, &OutputString) != 0x0000;) { + if ((Temp2 == 0) && (MenuOption->Row >= TopRow) && (MenuOption->Row <= BottomRow) ) { + PrintStringAt (MenuOption->OptCol, MenuOption->Row, OutputString); + } + // + // If there is more string to process print on the next row and increment the Skip value + // + if (StrLen (&OptionString[Index]) != 0) { + if (Temp2 == 0) { + MenuOption->Row++; + } + } + + FreePool (OutputString); + if (Temp2 != 0) { + Temp2--; + } + } + + MenuOption->Row = OriginalRow; + + FreePool (OptionString); + } else { + if (NewLine) { + OriginalRow = MenuOption->Row; + + Width = GetWidth (Statement, MenuOption->Handle); + GlyphWidth = 1; + + for (Index = 0; GetLineByWidth (MenuOption->Description, Width, &GlyphWidth, &Index, &OutputString) != 0x0000;) { + if ((Temp2 == 0) && (MenuOption->Row >= TopRow) && (MenuOption->Row <= BottomRow) ) { + PrintStringAt (MenuOption->Col, MenuOption->Row, OutputString); + } + // + // If there is more string to process print on the next row and increment the Skip value + // + if (StrLen (&MenuOption->Description[Index]) != 0) { + if (Temp2 == 0) { + MenuOption->Row++; + } + } + + FreePool (OutputString); + if (Temp2 != 0) { + Temp2--; + } + } + + MenuOption->Row = OriginalRow; + + } + } + + UpdateKeyHelp (Selection, MenuOption, FALSE); + + // + // Clear reverse attribute + // + gST->ConOut->SetAttribute (gST->ConOut, PcdGet8 (PcdBrowserFieldTextColor) | FIELD_BACKGROUND); + } + // + // Repaint flag will be used when process CfUpdateHelpString, so restore its value + // if we didn't break halfway when process CfRefreshHighLight. + // + Repaint = SavedValue; + break; + + case CfUpdateHelpString: + ControlFlag = CfPrepareToReadKey; + if (Selection->Form->ModalForm) { + break; + } + + if (Repaint || NewLine) { + // + // Don't print anything if it is a NULL help token + // + ASSERT(MenuOption != NULL); + if (MenuOption->ThisTag->Help == 0 || !IsSelectable (MenuOption)) { + StringPtr = L"\0"; + } else { + StringPtr = GetToken (MenuOption->ThisTag->Help, MenuOption->Handle); + } + + RowCount = BottomRow - TopRow; + HelpPageIndex = 0; + // + // 1.Calculate how many line the help string need to print. + // + if (HelpString != NULL) { + FreePool (HelpString); + } + HelpLine = ProcessHelpString (StringPtr, &HelpString, &EachLineWidth, RowCount); + if (HelpLine > RowCount) { + MultiHelpPage = TRUE; + StringPtr = GetToken (STRING_TOKEN(ADJUST_HELP_PAGE_UP), gHiiHandle); + if (HelpHeaderString != NULL) { + FreePool (HelpHeaderString); + } + HelpHeaderLine = ProcessHelpString (StringPtr, &HelpHeaderString, &HeaderLineWidth, RowCount); + StringPtr = GetToken (STRING_TOKEN(ADJUST_HELP_PAGE_DOWN), gHiiHandle); + if (HelpBottomString != NULL) { + FreePool (HelpBottomString); + } + HelpBottomLine = ProcessHelpString (StringPtr, &HelpBottomString, &BottomLineWidth, RowCount); + // + // Calculate the help page count. + // + if (HelpLine > 2 * RowCount - 2) { + HelpPageCount = (HelpLine - RowCount + 1) / (RowCount - 2) + 1; + if ((HelpLine - RowCount + 1) % (RowCount - 2) > 1) { + HelpPageCount += 1; + } + } else { + HelpPageCount = 2; + } + } else { + MultiHelpPage = FALSE; + } + } + + // + // Clean the help field first. + // + ClearLines ( + LocalScreen.RightColumn - gHelpBlockWidth, + LocalScreen.RightColumn, + TopRow, + BottomRow, + PcdGet8 (PcdBrowserFieldTextColor) | FIELD_BACKGROUND + ); + + // + // Check whether need to show the 'More(U/u)' at the begin. + // Base on current direct info, here shows aligned to the right side of the column. + // If the direction is multi line and aligned to right side may have problem, so + // add ASSERT code here. + // + if (HelpPageIndex > 0) { + gST->ConOut->SetAttribute (gST->ConOut, INFO_TEXT | FIELD_BACKGROUND); + for (Index = 0; Index < HelpHeaderLine; Index++) { + ASSERT (HelpHeaderLine == 1); + ASSERT (GetStringWidth (HelpHeaderString) / 2 < (UINTN) (gHelpBlockWidth - 1)); + PrintStringAt ( + LocalScreen.RightColumn - GetStringWidth (HelpHeaderString) / 2 - 1, + Index + TopRow, + &HelpHeaderString[Index * HeaderLineWidth] + ); + } + } + + gST->ConOut->SetAttribute (gST->ConOut, HELP_TEXT | FIELD_BACKGROUND); + // + // Print the help string info. + // + if (!MultiHelpPage) { + for (Index = 0; Index < HelpLine; Index++) { + PrintStringAt ( + LocalScreen.RightColumn - gHelpBlockWidth, + Index + TopRow, + &HelpString[Index * EachLineWidth] + ); + } + gST->ConOut->SetCursorPosition(gST->ConOut, LocalScreen.RightColumn-1, BottomRow); + } else { + if (HelpPageIndex == 0) { + for (Index = 0; Index < RowCount - HelpBottomLine; Index++) { + PrintStringAt ( + LocalScreen.RightColumn - gHelpBlockWidth, + Index + TopRow, + &HelpString[Index * EachLineWidth] + ); + } + } else { + for (Index = 0; (Index < RowCount - HelpBottomLine - HelpHeaderLine) && + (Index + HelpPageIndex * (RowCount - 2) + 1 < HelpLine); Index++) { + PrintStringAt ( + LocalScreen.RightColumn - gHelpBlockWidth, + Index + TopRow + HelpHeaderLine, + &HelpString[(Index + HelpPageIndex * (RowCount - 2) + 1)* EachLineWidth] + ); + } + if (HelpPageIndex == HelpPageCount - 1) { + gST->ConOut->SetCursorPosition(gST->ConOut, LocalScreen.RightColumn-1, BottomRow); + } + } + } + + // + // Check whether need to print the 'More(D/d)' at the bottom. + // Base on current direct info, here shows aligned to the right side of the column. + // If the direction is multi line and aligned to right side may have problem, so + // add ASSERT code here. + // + if (HelpPageIndex < HelpPageCount - 1 && MultiHelpPage) { + gST->ConOut->SetAttribute (gST->ConOut, INFO_TEXT | FIELD_BACKGROUND); + for (Index = 0; Index < HelpBottomLine; Index++) { + ASSERT (HelpBottomLine == 1); + ASSERT (GetStringWidth (HelpBottomString) / 2 < (UINTN) (gHelpBlockWidth - 1)); + PrintStringAt ( + LocalScreen.RightColumn - GetStringWidth (HelpBottomString) / 2 - 1, + Index + BottomRow - HelpBottomLine, + &HelpBottomString[Index * BottomLineWidth] + ); + } + } + // + // Reset this flag every time we finish using it. + // + Repaint = FALSE; + NewLine = FALSE; + break; + + case CfPrepareToReadKey: + ControlFlag = CfReadKey; + ScreenOperation = UiNoOperation; + break; + + case CfReadKey: + ControlFlag = CfScreenOperation; + + // + // Wait for user's selection + // + while (TRUE) { + Status = gST->ConIn->ReadKeyStroke (gST->ConIn, &Key); + if (!EFI_ERROR (Status)) { + break; + } + + // + // If we encounter error, continue to read another key in. + // + if (Status != EFI_NOT_READY) { + continue; + } + + Status = UiWaitForSingleEvent (gST->ConIn->WaitForKey, 0, MinRefreshInterval); + ASSERT_EFI_ERROR (Status); + + if (Selection->Action == UI_ACTION_REFRESH_FORMSET) { + // + // IFR is updated in Callback of refresh opcode, re-parse it + // + ControlFlag = CfCheckSelection; + Selection->Statement = NULL; + break; + } + } + + if (ControlFlag == CfCheckSelection) { + break; + } + + switch (Key.UnicodeChar) { + case CHAR_CARRIAGE_RETURN: + if(MenuOption->GrayOut || MenuOption->ReadOnly) { + ControlFlag = CfReadKey; + break; + } + + ScreenOperation = UiSelect; + gDirection = 0; + break; + + // + // We will push the adjustment of these numeric values directly to the input handler + // NOTE: we won't handle manual input numeric + // + case '+': + case '-': + // + // If the screen has no menu items, and the user didn't select UiReset + // ignore the selection and go back to reading keys. + // + if(IsListEmpty (&gMenuOption) || MenuOption->GrayOut || MenuOption->ReadOnly) { + ControlFlag = CfReadKey; + break; + } + + ASSERT(MenuOption != NULL); + Statement = MenuOption->ThisTag; + if ((Statement->Operand == EFI_IFR_DATE_OP) + || (Statement->Operand == EFI_IFR_TIME_OP) + || ((Statement->Operand == EFI_IFR_NUMERIC_OP) && (Statement->Step != 0)) + ){ + if (Key.UnicodeChar == '+') { + gDirection = SCAN_RIGHT; + } else { + gDirection = SCAN_LEFT; + } + Status = ProcessOptions (Selection, MenuOption, TRUE, &OptionString); + if (EFI_ERROR (Status)) { + // + // Repaint to clear possible error prompt pop-up + // + Repaint = TRUE; + NewLine = TRUE; + } else { + Selection->Action = UI_ACTION_REFRESH_FORM; + } + if (OptionString != NULL) { + FreePool (OptionString); + } + } + break; + + case '^': + ScreenOperation = UiUp; + break; + + case 'V': + case 'v': + ScreenOperation = UiDown; + break; + + case ' ': + if ((gClassOfVfr & FORMSET_CLASS_FRONT_PAGE) != FORMSET_CLASS_FRONT_PAGE) { + // + // If the screen has no menu items, and the user didn't select UiReset + // ignore the selection and go back to reading keys. + // + if(IsListEmpty (&gMenuOption)) { + ControlFlag = CfReadKey; + break; + } + + ASSERT(MenuOption != NULL); + if (MenuOption->ThisTag->Operand == EFI_IFR_CHECKBOX_OP && !MenuOption->GrayOut && !MenuOption->ReadOnly) { + ScreenOperation = UiSelect; + } + } + break; + + case 'D': + case 'd': + if (!MultiHelpPage) { + ControlFlag = CfReadKey; + break; + } + ControlFlag = CfUpdateHelpString; + HelpPageIndex = HelpPageIndex < HelpPageCount - 1 ? HelpPageIndex + 1 : HelpPageCount - 1; + break; + + case 'U': + case 'u': + if (!MultiHelpPage) { + ControlFlag = CfReadKey; + break; + } + ControlFlag = CfUpdateHelpString; + HelpPageIndex = HelpPageIndex > 0 ? HelpPageIndex - 1 : 0; + break; + + case CHAR_NULL: + for (Index = 0; Index < mScanCodeNumber; Index++) { + if (Key.ScanCode == gScanCodeToOperation[Index].ScanCode) { + ScreenOperation = gScanCodeToOperation[Index].ScreenOperation; + break; + } + } + + if (Selection->Form->ModalForm && (Key.ScanCode == SCAN_ESC || Index == mScanCodeNumber)) { + // + // ModalForm has no ESC key and Hot Key. + // + ControlFlag = CfReadKey; + } else if (Index == mScanCodeNumber) { + // + // Check whether Key matches the registered hot key. + // + HotKey = NULL; + if ((gBrowserSettingScope == SystemLevel) || + (Selection->FormEditable && gFunctionKeySetting != NONE_FUNCTION_KEY_SETTING)) { + HotKey = GetHotKeyFromRegisterList (&Key); + } + if (HotKey != NULL) { + ScreenOperation = UiHotKey; + } + } + break; + } + break; + + case CfScreenOperation: + if (ScreenOperation != UiReset) { + // + // If the screen has no menu items, and the user didn't select UiReset + // ignore the selection and go back to reading keys. + // + if (IsListEmpty (&gMenuOption)) { + ControlFlag = CfReadKey; + break; + } + } + + for (Index = 0; + Index < sizeof (gScreenOperationToControlFlag) / sizeof (gScreenOperationToControlFlag[0]); + Index++ + ) { + if (ScreenOperation == gScreenOperationToControlFlag[Index].ScreenOperation) { + ControlFlag = gScreenOperationToControlFlag[Index].ControlFlag; + break; + } + } + break; + + case CfUiSelect: + ControlFlag = CfCheckSelection; + + ASSERT(MenuOption != NULL); + Statement = MenuOption->ThisTag; + if (Statement->Operand == EFI_IFR_TEXT_OP) { + break; + } + + // + // Keep highlight on current MenuOption + // + Selection->QuestionId = Statement->QuestionId; + + switch (Statement->Operand) { + case EFI_IFR_REF_OP: + ProcessGotoOpCode(Statement, Selection, &Repaint, &NewLine); + break; + + case EFI_IFR_ACTION_OP: + // + // Process the Config string + // + Status = ProcessQuestionConfig (Selection, Statement); + + if (EFI_ERROR (Status)) { + break; + } + + // + // The action button may change some Question value, so refresh the form + // + Selection->Action = UI_ACTION_REFRESH_FORM; + break; + + case EFI_IFR_RESET_BUTTON_OP: + // + // Reset Question to default value specified by DefaultId + // + ControlFlag = CfUiDefault; + DefaultId = Statement->DefaultId; + break; + + default: + // + // Editable Questions: oneof, ordered list, checkbox, numeric, string, password + // + UpdateKeyHelp (Selection, MenuOption, TRUE); + Status = ProcessOptions (Selection, MenuOption, TRUE, &OptionString); + + if (EFI_ERROR (Status)) { + Repaint = TRUE; + NewLine = TRUE; + UpdateKeyHelp (Selection, MenuOption, FALSE); + } else { + Selection->Action = UI_ACTION_REFRESH_FORM; + } + + if (OptionString != NULL) { + FreePool (OptionString); + } + break; + } + break; + + case CfUiReset: + // + // We come here when someone press ESC + // + ControlFlag = CfCheckSelection; + FindNextMenu (Selection, &Repaint, &NewLine); + break; + + case CfUiLeft: + ControlFlag = CfCheckSelection; + ASSERT(MenuOption != NULL); + if ((MenuOption->ThisTag->Operand == EFI_IFR_DATE_OP) || (MenuOption->ThisTag->Operand == EFI_IFR_TIME_OP)) { + if (MenuOption->Sequence != 0) { + // + // In the middle or tail of the Date/Time op-code set, go left. + // + ASSERT(NewPos != NULL); + NewPos = NewPos->BackLink; + } + } + break; + + case CfUiRight: + ControlFlag = CfCheckSelection; + ASSERT(MenuOption != NULL); + if ((MenuOption->ThisTag->Operand == EFI_IFR_DATE_OP) || (MenuOption->ThisTag->Operand == EFI_IFR_TIME_OP)) { + if (MenuOption->Sequence != 2) { + // + // In the middle or tail of the Date/Time op-code set, go left. + // + ASSERT(NewPos != NULL); + NewPos = NewPos->ForwardLink; + } + } + break; + + case CfUiUp: + ControlFlag = CfCheckSelection; + + SavedListEntry = NewPos; + + ASSERT(NewPos != NULL); + // + // Adjust Date/Time position before we advance forward. + // + AdjustDateAndTimePosition (TRUE, &NewPos); + if (NewPos->BackLink != &gMenuOption) { + MenuOption = MENU_OPTION_FROM_LINK (NewPos); + ASSERT (MenuOption != NULL); + NewLine = TRUE; + NewPos = NewPos->BackLink; + + PreviousMenuOption = MENU_OPTION_FROM_LINK (NewPos); + if (PreviousMenuOption->Row == 0) { + UpdateOptionSkipLines (Selection, PreviousMenuOption); + } + DistanceValue = PreviousMenuOption->Skip; + Difference = 0; + if (MenuOption->Row >= DistanceValue + TopRow) { + Difference = MoveToNextStatement (Selection, TRUE, &NewPos, MenuOption->Row - TopRow - DistanceValue); + } + NextMenuOption = MENU_OPTION_FROM_LINK (NewPos); + + if (Difference < 0) { + // + // We hit the begining MenuOption that can be focused + // so we simply scroll to the top. + // + if (TopOfScreen != gMenuOption.ForwardLink) { + TopOfScreen = gMenuOption.ForwardLink; + Repaint = TRUE; + } else { + // + // Scroll up to the last page when we have arrived at top page. + // + NewPos = &gMenuOption; + TopOfScreen = &gMenuOption; + MenuOption = MENU_OPTION_FROM_LINK (SavedListEntry); + ScreenOperation = UiPageUp; + ControlFlag = CfScreenOperation; + break; + } + } else if (MenuOption->Row < TopRow + DistanceValue + Difference) { + // + // Previous focus MenuOption is above the TopOfScreen, so we need to scroll + // + TopOfScreen = NewPos; + Repaint = TRUE; + SkipValue = 0; + } else if (!IsSelectable (NextMenuOption)) { + // + // Continue to go up until scroll to next page or the selectable option is found. + // + ScreenOperation = UiUp; + ControlFlag = CfScreenOperation; + } + + // + // If we encounter a Date/Time op-code set, rewind to the first op-code of the set. + // + AdjustDateAndTimePosition (TRUE, &TopOfScreen); + AdjustDateAndTimePosition (TRUE, &NewPos); + MenuOption = MENU_OPTION_FROM_LINK (SavedListEntry); + UpdateStatusBar (Selection, INPUT_ERROR, MenuOption->ThisTag->QuestionFlags, FALSE); + } else { + // + // Scroll up to the last page. + // + NewPos = &gMenuOption; + TopOfScreen = &gMenuOption; + MenuOption = MENU_OPTION_FROM_LINK (SavedListEntry); + ScreenOperation = UiPageUp; + ControlFlag = CfScreenOperation; + } + break; + + case CfUiPageUp: + // + // SkipValue means lines is skipped when show the top menu option. + // + ControlFlag = CfCheckSelection; + + ASSERT(NewPos != NULL); + // + // Already at the first menu option, so do nothing. + // + if (NewPos->BackLink == &gMenuOption) { + NewLine = FALSE; + Repaint = FALSE; + break; + } + + NewLine = TRUE; + Repaint = TRUE; + + // + // SkipValue > (BottomRow - TopRow + 1) means current menu has more than one + // form of options to be show, so just update the SkipValue to show the next + // parts of options. + // + if (SkipValue > (INTN) (BottomRow - TopRow + 1)) { + SkipValue -= BottomRow - TopRow + 1; + break; + } + + Link = TopOfScreen; + // + // First minus the menu of the top screen, it's value is SkipValue. + // + Index = (BottomRow + 1) - SkipValue; + while ((Index >= TopRow) && (Link->BackLink != &gMenuOption)) { + Link = Link->BackLink; + PreviousMenuOption = MENU_OPTION_FROM_LINK (Link); + if (PreviousMenuOption->Row == 0) { + UpdateOptionSkipLines (Selection, PreviousMenuOption); + } + if (Index < PreviousMenuOption->Skip) { + break; + } + Index = Index - PreviousMenuOption->Skip; + } + + if ((Link->BackLink == &gMenuOption) && (Index >= TopRow)) { + SkipValue = 0; + if (TopOfScreen == &gMenuOption) { + TopOfScreen = gMenuOption.ForwardLink; + NewPos = gMenuOption.BackLink; + MoveToNextStatement (Selection, TRUE, &NewPos, BottomRow - TopRow); + Repaint = FALSE; + } else if (TopOfScreen != Link) { + TopOfScreen = Link; + NewPos = Link; + MoveToNextStatement (Selection, FALSE, &NewPos, BottomRow - TopRow); + } else { + // + // Finally we know that NewPos is the last MenuOption can be focused. + // + Repaint = FALSE; + NewPos = Link; + MoveToNextStatement (Selection, FALSE, &NewPos, BottomRow - TopRow); + } + } else { + if (Index >= TopRow) { + // + // At here, only case "Index < PreviousMenuOption->Skip" can reach here. + // + SkipValue = PreviousMenuOption->Skip - (Index - TopRow); + } else { + SkipValue = PreviousMenuOption->Skip - (TopRow - Index); + Link = Link->ForwardLink; + } + + // + // Move to the option in Next page. + // + if (TopOfScreen == &gMenuOption) { + NewPos = gMenuOption.BackLink; + MoveToNextStatement (Selection, TRUE, &NewPos, BottomRow - TopRow); + } else { + NewPos = Link; + MoveToNextStatement (Selection, FALSE, &NewPos, BottomRow - TopRow); + } + + // + // There are more MenuOption needing scrolling up. + // + TopOfScreen = Link; + MenuOption = NULL; + } + + // + // If we encounter a Date/Time op-code set, rewind to the first op-code of the set. + // Don't do this when we are already in the first page. + // + AdjustDateAndTimePosition (TRUE, &TopOfScreen); + AdjustDateAndTimePosition (TRUE, &NewPos); + break; + + case CfUiPageDown: + // + // SkipValue means lines is skipped when show the top menu option. + // + ControlFlag = CfCheckSelection; + + ASSERT (NewPos != NULL); + if (NewPos->ForwardLink == &gMenuOption) { + NewLine = FALSE; + Repaint = FALSE; + break; + } + + NewLine = TRUE; + Repaint = TRUE; + Link = TopOfScreen; + NextMenuOption = MENU_OPTION_FROM_LINK (Link); + Index = TopRow + NextMenuOption->Skip - SkipValue; + // + // Count to the menu option which will show at the top of the next form. + // + while ((Index <= BottomRow + 1) && (Link->ForwardLink != &gMenuOption)) { + Link = Link->ForwardLink; + NextMenuOption = MENU_OPTION_FROM_LINK (Link); + Index = Index + NextMenuOption->Skip; + } + + if ((Link->ForwardLink == &gMenuOption) && (Index <= BottomRow + 1)) { + // + // Finally we know that NewPos is the last MenuOption can be focused. + // + Repaint = FALSE; + MoveToNextStatement (Selection, TRUE, &Link, Index - TopRow); + SkipValue = 0; + } else { + // + // Calculate the skip line for top of screen menu. + // + if (Link == TopOfScreen) { + // + // The top of screen menu option occupies the entire form. + // + SkipValue += BottomRow - TopRow + 1; + } else { + SkipValue = NextMenuOption->Skip - (Index - (BottomRow + 1)); + } + + TopOfScreen = Link; + MenuOption = NULL; + // + // Move to the Next selectable menu. + // + MoveToNextStatement (Selection, FALSE, &Link, BottomRow - TopRow); + } + + // + // Save the menu as the next highlight menu. + // + NewPos = Link; + + // + // If we encounter a Date/Time op-code set, rewind to the first op-code of the set. + // Don't do this when we are already in the last page. + // + AdjustDateAndTimePosition (TRUE, &TopOfScreen); + AdjustDateAndTimePosition (TRUE, &NewPos); + break; + + case CfUiDown: + // + // SkipValue means lines is skipped when show the top menu option. + // NewPos points to the menu which is highlighted now. + // + ControlFlag = CfCheckSelection; + // + // Since the behavior of hitting the down arrow on a Date/Time op-code is intended + // to be one that progresses to the next set of op-codes, we need to advance to the last + // Date/Time op-code and leave the remaining logic in UiDown intact so the appropriate + // checking can be done. The only other logic we need to introduce is that if a Date/Time + // op-code is the last entry in the menu, we need to rewind back to the first op-code of + // the Date/Time op-code. + // + SavedListEntry = NewPos; + AdjustDateAndTimePosition (FALSE, &NewPos); + + if (NewPos->ForwardLink != &gMenuOption) { + MenuOption = MENU_OPTION_FROM_LINK (NewPos); + NewLine = TRUE; + NewPos = NewPos->ForwardLink; + + Difference = 0; + // + // Current menu not at the bottom of the form. + // + if (BottomRow >= MenuOption->Row + MenuOption->Skip) { + // + // Find the next selectable menu. + // + Difference = MoveToNextStatement (Selection, FALSE, &NewPos, BottomRow - MenuOption->Row - MenuOption->Skip); + // + // We hit the end of MenuOption that can be focused + // so we simply scroll to the first page. + // + if (Difference < 0) { + // + // Scroll to the first page. + // + if (TopOfScreen != gMenuOption.ForwardLink) { + TopOfScreen = gMenuOption.ForwardLink; + Repaint = TRUE; + MenuOption = NULL; + } else { + MenuOption = MENU_OPTION_FROM_LINK (SavedListEntry); + } + NewPos = gMenuOption.ForwardLink; + MoveToNextStatement (Selection, FALSE, &NewPos, BottomRow - TopRow); + + SkipValue = 0; + // + // If we are at the end of the list and sitting on a Date/Time op, rewind to the head. + // + AdjustDateAndTimePosition (TRUE, &TopOfScreen); + AdjustDateAndTimePosition (TRUE, &NewPos); + break; + } + } + NextMenuOption = MENU_OPTION_FROM_LINK (NewPos); + if (NextMenuOption->Row == 0) { + UpdateOptionSkipLines (Selection, NextMenuOption); + } + DistanceValue = Difference + NextMenuOption->Skip; + + Temp = MenuOption->Row + MenuOption->Skip + DistanceValue - 1; + if ((MenuOption->Row + MenuOption->Skip == BottomRow + 1) && + (NextMenuOption->ThisTag->Operand == EFI_IFR_DATE_OP || + NextMenuOption->ThisTag->Operand == EFI_IFR_TIME_OP) + ) { + Temp ++; + } + + // + // If we are going to scroll, update TopOfScreen + // + if (Temp > BottomRow) { + do { + // + // Is the current top of screen a zero-advance op-code? + // If so, keep moving forward till we hit a >0 advance op-code + // + SavedMenuOption = MENU_OPTION_FROM_LINK (TopOfScreen); + + // + // If bottom op-code is more than one line or top op-code is more than one line + // + if ((DistanceValue > 1) || (SavedMenuOption->Skip > 1)) { + // + // Is the bottom op-code greater than or equal in size to the top op-code? + // + if ((Temp - BottomRow) >= (SavedMenuOption->Skip - SkipValue)) { + // + // Skip the top op-code + // + TopOfScreen = TopOfScreen->ForwardLink; + Difference = (Temp - BottomRow) - (SavedMenuOption->Skip - SkipValue); + + SavedMenuOption = MENU_OPTION_FROM_LINK (TopOfScreen); + + // + // If we have a remainder, skip that many more op-codes until we drain the remainder + // + while (Difference >= (INTN) SavedMenuOption->Skip) { + // + // Since the Difference is greater than or equal to this op-code's skip value, skip it + // + Difference = Difference - (INTN) SavedMenuOption->Skip; + TopOfScreen = TopOfScreen->ForwardLink; + SavedMenuOption = MENU_OPTION_FROM_LINK (TopOfScreen); + } + // + // Since we will act on this op-code in the next routine, and increment the + // SkipValue, set the skips to one less than what is required. + // + SkipValue = Difference - 1; + } else { + // + // Since we will act on this op-code in the next routine, and increment the + // SkipValue, set the skips to one less than what is required. + // + SkipValue += (Temp - BottomRow) - 1; + } + } else { + if ((SkipValue + 1) == (INTN) SavedMenuOption->Skip) { + TopOfScreen = TopOfScreen->ForwardLink; + break; + } + } + // + // If the op-code at the top of the screen is more than one line, let's not skip it yet + // Let's set a skip flag to smoothly scroll the top of the screen. + // + if (SavedMenuOption->Skip > 1) { + if (SavedMenuOption == NextMenuOption) { + SkipValue = 0; + } else { + SkipValue++; + } + } else if (SavedMenuOption->Skip == 1) { + SkipValue = 0; + } else { + SkipValue = 0; + TopOfScreen = TopOfScreen->ForwardLink; + } + } while (SavedMenuOption->Skip == 0); + + Repaint = TRUE; + } else if (!IsSelectable (NextMenuOption)) { + // + // Continue to go down until scroll to next page or the selectable option is found. + // + ScreenOperation = UiDown; + ControlFlag = CfScreenOperation; + } + + MenuOption = MENU_OPTION_FROM_LINK (SavedListEntry); + + UpdateStatusBar (Selection, INPUT_ERROR, MenuOption->ThisTag->QuestionFlags, FALSE); + + } else { + // + // Scroll to the first page. + // + if (TopOfScreen != gMenuOption.ForwardLink) { + TopOfScreen = gMenuOption.ForwardLink; + Repaint = TRUE; + MenuOption = NULL; + } else { + // + // Need to remove the current highlight menu. + // MenuOption saved the last highlight menu info. + // + MenuOption = MENU_OPTION_FROM_LINK (SavedListEntry); + } + + SkipValue = 0; + NewLine = TRUE; + // + // Get the next highlight menu. + // + NewPos = gMenuOption.ForwardLink; + MoveToNextStatement (Selection, FALSE, &NewPos, BottomRow - TopRow); + } + + // + // If we are at the end of the list and sitting on a Date/Time op, rewind to the head. + // + AdjustDateAndTimePosition (TRUE, &TopOfScreen); + AdjustDateAndTimePosition (TRUE, &NewPos); + break; + + case CfUiHotKey: + ControlFlag = CfCheckSelection; + + Status = EFI_SUCCESS; + // + // Discard changes. After it, no NV flag is showed. + // + if ((HotKey->Action & BROWSER_ACTION_DISCARD) == BROWSER_ACTION_DISCARD) { + Status = DiscardForm (Selection->FormSet, Selection->Form, gBrowserSettingScope); + if (!EFI_ERROR (Status)) { + Selection->Action = UI_ACTION_REFRESH_FORM; + Selection->Statement = NULL; + gResetRequired = FALSE; + } else { + do { + CreateDialog (4, TRUE, 0, NULL, &Key, HotKey->HelpString, gDiscardFailed, gPressEnter, gEmptyString); + } while (Key.UnicodeChar != CHAR_CARRIAGE_RETURN); + // + // Still show current page. + // + Selection->Action = UI_ACTION_NONE; + Repaint = TRUE; + NewLine = TRUE; + break; + } + } + + // + // Reterieve default setting. After it. NV flag will be showed. + // + if ((HotKey->Action & BROWSER_ACTION_DEFAULT) == BROWSER_ACTION_DEFAULT) { + Status = ExtractDefault (Selection->FormSet, Selection->Form, HotKey->DefaultId, gBrowserSettingScope, GetDefaultForAll, NULL, FALSE); + if (!EFI_ERROR (Status)) { + Selection->Action = UI_ACTION_REFRESH_FORM; + Selection->Statement = NULL; + gResetRequired = TRUE; + } else { + do { + CreateDialog (4, TRUE, 0, NULL, &Key, HotKey->HelpString, gDefaultFailed, gPressEnter, gEmptyString); + } while (Key.UnicodeChar != CHAR_CARRIAGE_RETURN); + // + // Still show current page. + // + Selection->Action = UI_ACTION_NONE; + Repaint = TRUE; + NewLine = TRUE; + break; + } + } + + // + // Save changes. After it, no NV flag is showed. + // + if ((HotKey->Action & BROWSER_ACTION_SUBMIT) == BROWSER_ACTION_SUBMIT) { + Status = SubmitForm (Selection->FormSet, Selection->Form, gBrowserSettingScope); + if (!EFI_ERROR (Status)) { + ASSERT(MenuOption != NULL); + UpdateStatusBar (Selection, INPUT_ERROR, MenuOption->ThisTag->QuestionFlags, FALSE); + UpdateStatusBar (Selection, NV_UPDATE_REQUIRED, MenuOption->ThisTag->QuestionFlags, FALSE); + } else { + do { + CreateDialog (4, TRUE, 0, NULL, &Key, HotKey->HelpString, gSaveFailed, gPressEnter, gEmptyString); + } while (Key.UnicodeChar != CHAR_CARRIAGE_RETURN); + // + // Still show current page. + // + Selection->Action = UI_ACTION_NONE; + Repaint = TRUE; + NewLine = TRUE; + break; + } + } + + // + // Set Reset required Flag + // + if ((HotKey->Action & BROWSER_ACTION_RESET) == BROWSER_ACTION_RESET) { + gResetRequired = TRUE; + } + + // + // Exit Action + // + if ((HotKey->Action & BROWSER_ACTION_EXIT) == BROWSER_ACTION_EXIT) { + // + // Form Exit without saving, Similar to ESC Key. + // FormSet Exit without saving, Exit SendForm. + // System Exit without saving, CallExitHandler and Exit SendForm. + // + DiscardForm (Selection->FormSet, Selection->Form, gBrowserSettingScope); + if (gBrowserSettingScope == FormLevel) { + ControlFlag = CfUiReset; + } else if (gBrowserSettingScope == FormSetLevel) { + Selection->Action = UI_ACTION_EXIT; + } else if (gBrowserSettingScope == SystemLevel) { + if (ExitHandlerFunction != NULL) { + ExitHandlerFunction (); + } + Selection->Action = UI_ACTION_EXIT; + } + Selection->Statement = NULL; + } + break; + + case CfUiDefault: + ControlFlag = CfCheckSelection; + // + // Reset to default value for all forms in the whole system. + // + Status = ExtractDefault (Selection->FormSet, NULL, DefaultId, FormSetLevel, GetDefaultForAll, NULL, FALSE); + + if (!EFI_ERROR (Status)) { + Selection->Action = UI_ACTION_REFRESH_FORM; + Selection->Statement = NULL; + gResetRequired = TRUE; + } + break; + + case CfUiNoOperation: + ControlFlag = CfCheckSelection; + break; + + case CfExit: + UiFreeRefreshList (); + + gST->ConOut->SetAttribute (gST->ConOut, EFI_TEXT_ATTR (EFI_LIGHTGRAY, EFI_BLACK)); + gST->ConOut->SetCursorPosition (gST->ConOut, 0, Row + 4); + gST->ConOut->EnableCursor (gST->ConOut, TRUE); + gST->ConOut->OutputString (gST->ConOut, L"\n"); + if (HelpString != NULL) { + FreePool (HelpString); + } + if (HelpHeaderString != NULL) { + FreePool (HelpHeaderString); + } + if (HelpBottomString != NULL) { + FreePool (HelpBottomString); + } + + return EFI_SUCCESS; + + default: + break; + } + } +} diff --git a/MdeModulePkg/Universal/SetupBrowserDxe/Ui.h b/MdeModulePkg/Universal/SetupBrowserDxe/Ui.h new file mode 100644 index 0000000000..03cb0cd753 --- /dev/null +++ b/MdeModulePkg/Universal/SetupBrowserDxe/Ui.h @@ -0,0 +1,1067 @@ +/** @file +Private structure, MACRO and function definitions for User Interface related functionalities. + +Copyright (c) 2004 - 2013, Intel Corporation. All rights reserved.
+This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef _UI_H_ +#define _UI_H_ + +// +// Globals +// +#define REGULAR_NUMERIC 0 +#define TIME_NUMERIC 1 +#define DATE_NUMERIC 2 + +#define SUBTITLE_INDENT 2 + + +// +// It take 23 characters including the NULL to print a 64 bits number with "[" and "]". +// pow(2, 64) = [18446744073709551616] +// +#define MAX_NUMERIC_INPUT_WIDTH 23 + +typedef enum { + UiNoOperation, + UiSelect, + UiUp, + UiDown, + UiLeft, + UiRight, + UiReset, + UiPrevious, + UiPageUp, + UiPageDown, + UiHotKey, + UiMaxOperation +} UI_SCREEN_OPERATION; + +typedef enum { + CfInitialization, + CfCheckSelection, + CfRepaint, + CfRefreshHighLight, + CfUpdateHelpString, + CfPrepareToReadKey, + CfReadKey, + CfScreenOperation, + CfUiSelect, + CfUiReset, + CfUiLeft, + CfUiRight, + CfUiUp, + CfUiPageUp, + CfUiPageDown, + CfUiDown, + CfUiDefault, + CfUiNoOperation, + CfExit, + CfUiHotKey, + CfMaxControlFlag +} UI_CONTROL_FLAG; + +#define UI_ACTION_NONE 0 +#define UI_ACTION_REFRESH_FORM 1 +#define UI_ACTION_REFRESH_FORMSET 2 +#define UI_ACTION_EXIT 3 + +typedef struct _UI_MENU_LIST UI_MENU_LIST; + +typedef struct { + EFI_HII_HANDLE Handle; + + // + // Target formset/form/Question information + // + EFI_GUID FormSetGuid; + UINT16 FormId; + UINT16 QuestionId; + UINTN Sequence; // used for time/date only. + + UINTN TopRow; + UINTN BottomRow; + UINTN PromptCol; + UINTN OptionCol; + UINTN CurrentRow; + + // + // Ation for Browser to taken: + // UI_ACTION_NONE - navigation inside a form + // UI_ACTION_REFRESH_FORM - re-evaluate expressions and repaint form + // UI_ACTION_REFRESH_FORMSET - re-parse formset IFR binary + // + UINTN Action; + + // + // Current selected fomset/form/Question + // + FORM_BROWSER_FORMSET *FormSet; + FORM_BROWSER_FORM *Form; + FORM_BROWSER_STATEMENT *Statement; + + // + // Whether the Form is editable + // + BOOLEAN FormEditable; + + UI_MENU_LIST *CurrentMenu; +} UI_MENU_SELECTION; + +#define UI_MENU_OPTION_SIGNATURE SIGNATURE_32 ('u', 'i', 'm', 'm') +#define UI_MENU_LIST_SIGNATURE SIGNATURE_32 ('u', 'i', 'm', 'l') + +typedef struct { + UINTN Signature; + LIST_ENTRY Link; + + EFI_HII_HANDLE Handle; + FORM_BROWSER_STATEMENT *ThisTag; + UINT16 EntryNumber; + + UINTN Row; + UINTN Col; + UINTN OptCol; + CHAR16 *Description; + UINTN Skip; // Number of lines + + // + // Display item sequence for date/time + // Date: Month/Day/Year + // Sequence: 0 1 2 + // + // Time: Hour : Minute : Second + // Sequence: 0 1 2 + // + // + UINTN Sequence; + + BOOLEAN GrayOut; + BOOLEAN ReadOnly; + + // + // Whether user could change value of this item + // + BOOLEAN IsQuestion; +} UI_MENU_OPTION; + +#define MENU_OPTION_FROM_LINK(a) CR (a, UI_MENU_OPTION, Link, UI_MENU_OPTION_SIGNATURE) + +struct _UI_MENU_LIST { + UINTN Signature; + LIST_ENTRY Link; + + EFI_HII_HANDLE HiiHandle; + EFI_GUID FormSetGuid; + UINT16 FormId; + UINT16 QuestionId; + UINTN Sequence; // used for time/date only. + + UI_MENU_LIST *Parent; + LIST_ENTRY ChildListHead; +}; + +#define UI_MENU_LIST_FROM_LINK(a) CR (a, UI_MENU_LIST, Link, UI_MENU_LIST_SIGNATURE) + +typedef struct _MENU_REFRESH_ENTRY MENU_REFRESH_ENTRY; +struct _MENU_REFRESH_ENTRY { + MENU_REFRESH_ENTRY *Next; + UI_MENU_OPTION *MenuOption; // Describes the entry needing an update + UI_MENU_SELECTION *Selection; + UINTN CurrentColumn; + UINTN CurrentRow; + UINTN CurrentAttribute; + EFI_EVENT Event; +}; + +typedef struct { + UINT16 ScanCode; + UI_SCREEN_OPERATION ScreenOperation; +} SCAN_CODE_TO_SCREEN_OPERATION; + +typedef struct { + UI_SCREEN_OPERATION ScreenOperation; + UI_CONTROL_FLAG ControlFlag; +} SCREEN_OPERATION_T0_CONTROL_FLAG; + + +extern LIST_ENTRY gMenuOption; +extern LIST_ENTRY gMenuList; +extern MENU_REFRESH_ENTRY *gMenuRefreshHead; +extern UI_MENU_SELECTION *gCurrentSelection; +extern BOOLEAN mHiiPackageListUpdated; + +// +// Global Functions +// +/** + Initialize Menu option list. + +**/ +VOID +UiInitMenu ( + VOID + ); + +/** + Initialize Menu option list. + +**/ +VOID +UiInitMenuList ( + VOID + ); + +/** + Free Menu option linked list. + +**/ +VOID +UiFreeMenu ( + VOID + ); + +/** + Create a menu with specified formset GUID and form ID, and add it as a child + of the given parent menu. + + @param Parent The parent of menu to be added. + @param HiiHandle Hii handle related to this formset. + @param FormSetGuid The Formset Guid of menu to be added. + @param FormId The Form ID of menu to be added. + + @return A pointer to the newly added menu or NULL if memory is insufficient. + +**/ +UI_MENU_LIST * +UiAddMenuList ( + IN OUT UI_MENU_LIST *Parent, + IN EFI_HII_HANDLE HiiHandle, + IN EFI_GUID *FormSetGuid, + IN UINT16 FormId + ); + +/** + Search Menu with given FormId, FormSetGuid and Handle in all cached menu list. + + @param Parent The parent of menu to search. + @param Handle Hii handle related to this formset. + @param FormSetGuid The Formset GUID of the menu to search. + @param FormId The Form ID of menu to search. + + @return A pointer to menu found or NULL if not found. + +**/ +UI_MENU_LIST * +UiFindChildMenuList ( + IN UI_MENU_LIST *Parent, + IN EFI_HII_HANDLE Handle, + IN EFI_GUID *FormSetGuid, + IN UINT16 FormId + ); + +/** + Search Menu with given Handle, FormSetGuid and FormId in all cached menu list. + + @param Handle Hii handle related to this formset. + @param FormSetGuid The Formset GUID of the menu to search. + @param FormId The Form ID of menu to search. + + @return A pointer to menu found or NULL if not found. + +**/ +UI_MENU_LIST * +UiFindMenuList ( + IN EFI_HII_HANDLE Handle, + IN EFI_GUID *FormSetGuid, + IN UINT16 FormId + ); + +/** + Free Menu list linked list. + + @param MenuListHead One Menu list point in the menu list. + +**/ +VOID +UiFreeMenuList ( + LIST_ENTRY *MenuListHead + ); + +/** + Free Menu option linked list. + +**/ +VOID +UiFreeRefreshList ( + VOID + ); + +/** + Add one menu option by specified description and context. + + @param String String description for this option. + @param Handle Hii handle for the package list. + @param Form The form this statement belong to. + @param Statement Statement of this Menu Option. + @param NumberOfLines Display lines for this Menu Option. + @param MenuItemCount The index for this Option in the Menu. + + @retval Pointer Pointer to the added Menu Option. + +**/ +UI_MENU_OPTION * +UiAddMenuOption ( + IN CHAR16 *String, + IN EFI_HII_HANDLE Handle, + IN FORM_BROWSER_FORM *Form, + IN FORM_BROWSER_STATEMENT *Statement, + IN UINT16 NumberOfLines, + IN UINT16 MenuItemCount + ); + +/** + Display menu and wait for user to select one menu option, then return it. + If AutoBoot is enabled, then if user doesn't select any option, + after period of time, it will automatically return the first menu option. + + @param Selection Menu selection. + + @return Return the pointer of the menu which selected, + @return otherwise return NULL. + +**/ +EFI_STATUS +UiDisplayMenu ( + IN OUT UI_MENU_SELECTION *Selection + ); + +/** + Free up the resource allocated for all strings required + by Setup Browser. + +**/ +VOID +FreeBrowserStrings ( + VOID + ); + +/** + Process the goto op code, update the info in the selection structure. + + @param Statement The statement belong to goto op code. + @param Selection The selection info. + @param Repaint Whether need to repaint the menu. + @param NewLine Whether need to create new line. + + @retval EFI_SUCCESS The menu process successfully. + @return Other value if the process failed. +**/ +EFI_STATUS +ProcessGotoOpCode ( + IN OUT FORM_BROWSER_STATEMENT *Statement, + IN OUT UI_MENU_SELECTION *Selection, + OUT BOOLEAN *Repaint, + OUT BOOLEAN *NewLine + ); + + +/** + The worker function that send the displays to the screen. On output, + the selection made by user is returned. + + @param Selection On input, Selection tell setup browser the information + about the Selection, form and formset to be displayed. + On output, Selection return the screen item that is selected + by user. + + @retval EFI_SUCCESS The page is displayed successfully. + @return Other value if the page failed to be diplayed. + +**/ +EFI_STATUS +SetupBrowser ( + IN OUT UI_MENU_SELECTION *Selection + ); + +/** + Set Buffer to Value for Size bytes. + + @param Buffer Memory to set. + @param Size Number of bytes to set + @param Value Value of the set operation. + +**/ +VOID +SetUnicodeMem ( + IN VOID *Buffer, + IN UINTN Size, + IN CHAR16 Value + ); + +/** + Wait for a given event to fire, or for an optional timeout to expire. + + @param Event The event to wait for + @param Timeout An optional timeout value in 100 ns units. + @param RefreshInterval Menu refresh interval (in seconds). + + @retval EFI_SUCCESS Event fired before Timeout expired. + @retval EFI_TIME_OUT Timout expired before Event fired. + +**/ +EFI_STATUS +UiWaitForSingleEvent ( + IN EFI_EVENT Event, + IN UINT64 Timeout, OPTIONAL + IN UINT8 RefreshInterval OPTIONAL + ); + +/** + Draw a pop up windows based on the dimension, number of lines and + strings specified. + + @param ScreenWidth The width of the pop-up. + @param NumberOfLines The number of lines. + @param ... A series of text strings that displayed in the pop-up. + +**/ +VOID +EFIAPI +CreateMultiStringPopUp ( + IN UINTN ScreenWidth, + IN UINTN NumberOfLines, + ... + ); + +/** + Get string or password input from user. + + @param MenuOption Pointer to the current input menu. + @param Prompt The prompt string shown on popup window. + @param StringPtr Old user input and destination for use input string. + + @retval EFI_SUCCESS If string input is read successfully + @retval EFI_DEVICE_ERROR If operation fails + +**/ +EFI_STATUS +ReadString ( + IN UI_MENU_OPTION *MenuOption, + IN CHAR16 *Prompt, + IN OUT CHAR16 *StringPtr + ); + +/** + Get selection for OneOf and OrderedList (Left/Right will be ignored). + + @param Selection Pointer to current selection. + @param MenuOption Pointer to the current input menu. + + @retval EFI_SUCCESS If Option input is processed successfully + @retval EFI_DEVICE_ERROR If operation fails + +**/ +EFI_STATUS +GetSelectionInputPopUp ( + IN UI_MENU_SELECTION *Selection, + IN UI_MENU_OPTION *MenuOption + ); + +/** + This routine reads a numeric value from the user input. + + @param Selection Pointer to current selection. + @param MenuOption Pointer to the current input menu. + + @retval EFI_SUCCESS If numerical input is read successfully + @retval EFI_DEVICE_ERROR If operation fails + +**/ +EFI_STATUS +GetNumericInput ( + IN UI_MENU_SELECTION *Selection, + IN UI_MENU_OPTION *MenuOption + ); + +/** + Update status bar on the bottom of menu. + + @param Selection Current selection info. + @param MessageType The type of message to be shown. + @param Flags The flags in Question header. + @param State Set or clear. + +**/ +VOID +UpdateStatusBar ( + IN UI_MENU_SELECTION *Selection, + IN UINTN MessageType, + IN UINT8 Flags, + IN BOOLEAN State + ); + +/** + Process Question Config. + + @param Selection The UI menu selection. + @param Question The Question to be peocessed. + + @retval EFI_SUCCESS Question Config process success. + @retval Other Question Config process fail. + +**/ +EFI_STATUS +ProcessQuestionConfig ( + IN UI_MENU_SELECTION *Selection, + IN FORM_BROWSER_STATEMENT *Question + ); + +/** + Print Question Value according to it's storage width and display attributes. + + @param Question The Question to be printed. + @param FormattedNumber Buffer for output string. + @param BufferSize The FormattedNumber buffer size in bytes. + + @retval EFI_SUCCESS Print success. + @retval EFI_BUFFER_TOO_SMALL Buffer size is not enough for formatted number. + +**/ +EFI_STATUS +PrintFormattedNumber ( + IN FORM_BROWSER_STATEMENT *Question, + IN OUT CHAR16 *FormattedNumber, + IN UINTN BufferSize + ); + +/** + Search an Option of a Question by its value. + + @param Question The Question + @param OptionValue Value for Option to be searched. + + @retval Pointer Pointer to the found Option. + @retval NULL Option not found. + +**/ +QUESTION_OPTION * +ValueToOption ( + IN FORM_BROWSER_STATEMENT *Question, + IN EFI_HII_VALUE *OptionValue + ); + +/** + Return data element in an Array by its Index. + + @param Array The data array. + @param Type Type of the data in this array. + @param Index Zero based index for data in this array. + + @retval Value The data to be returned + +**/ +UINT64 +GetArrayData ( + IN VOID *Array, + IN UINT8 Type, + IN UINTN Index + ); + +/** + Set value of a data element in an Array by its Index. + + @param Array The data array. + @param Type Type of the data in this array. + @param Index Zero based index for data in this array. + @param Value The value to be set. + +**/ +VOID +SetArrayData ( + IN VOID *Array, + IN UINT8 Type, + IN UINTN Index, + IN UINT64 Value + ); + +/** + Check whether this value already in the array, if yes, return the index. + + @param Array The data array. + @param Type Type of the data in this array. + @param Value The value to be find. + @param Index The index in the array which has same value with Value. + + @retval TRUE Found the value in the array. + @retval FALSE Not found the value. + +**/ +BOOLEAN +FindArrayData ( + IN VOID *Array, + IN UINT8 Type, + IN UINT64 Value, + OUT UINTN *Index OPTIONAL + ); + +/** + Process a Question's Option (whether selected or un-selected). + + @param Selection Pointer to UI_MENU_SELECTION. + @param MenuOption The MenuOption for this Question. + @param Selected TRUE: if Question is selected. + @param OptionString Pointer of the Option String to be displayed. + + @retval EFI_SUCCESS Question Option process success. + @retval Other Question Option process fail. + +**/ +EFI_STATUS +ProcessOptions ( + IN UI_MENU_SELECTION *Selection, + IN UI_MENU_OPTION *MenuOption, + IN BOOLEAN Selected, + OUT CHAR16 **OptionString + ); + +/** + Process the help string: Split StringPtr to several lines of strings stored in + FormattedString and the glyph width of each line cannot exceed gHelpBlockWidth. + + @param StringPtr The entire help string. + @param FormattedString The oupput formatted string. + @param EachLineWidth The string length of each line in the formatted string. + @param RowCount TRUE: if Question is selected. + +**/ +UINTN +ProcessHelpString ( + IN CHAR16 *StringPtr, + OUT CHAR16 **FormattedString, + OUT UINT16 *EachLineWidth, + IN UINTN RowCount + ); + +/** + Update key's help imformation. + + @param Selection Tell setup browser the information about the Selection + @param MenuOption The Menu option + @param Selected Whether or not a tag be selected + +**/ +VOID +UpdateKeyHelp ( + IN UI_MENU_SELECTION *Selection, + IN UI_MENU_OPTION *MenuOption, + IN BOOLEAN Selected + ); + +/** + Clear retangle with specified text attribute. + + @param LeftColumn Left column of retangle. + @param RightColumn Right column of retangle. + @param TopRow Start row of retangle. + @param BottomRow End row of retangle. + @param TextAttribute The character foreground and background. + +**/ +VOID +ClearLines ( + IN UINTN LeftColumn, + IN UINTN RightColumn, + IN UINTN TopRow, + IN UINTN BottomRow, + IN UINTN TextAttribute + ); + +/** + Count the storage space of a Unicode string. + + This function handles the Unicode string with NARROW_CHAR + and WIDE_CHAR control characters. NARROW_HCAR and WIDE_CHAR + does not count in the resultant output. If a WIDE_CHAR is + hit, then 2 Unicode character will consume an output storage + space with size of CHAR16 till a NARROW_CHAR is hit. + + If String is NULL, then ASSERT (). + + @param String The input string to be counted. + + @return Storage space for the input string. + +**/ +UINTN +GetStringWidth ( + IN CHAR16 *String + ); + +/** + Will copy LineWidth amount of a string in the OutputString buffer and return the + number of CHAR16 characters that were copied into the OutputString buffer. + In the code, it deals \r,\n,\r\n same as \n\r, also it not process the \r or \g. + + @param InputString String description for this option. + @param LineWidth Width of the desired string to extract in CHAR16 + characters + @param GlyphWidth The glyph width of the beging char in the string. + @param Index Where in InputString to start the copy process + @param OutputString Buffer to copy the string into + + @return Returns the number of CHAR16 characters that were copied into the OutputString buffer. + +**/ +UINT16 +GetLineByWidth ( + IN CHAR16 *InputString, + IN UINT16 LineWidth, + IN OUT UINT16 *GlyphWidth, + IN OUT UINTN *Index, + OUT CHAR16 **OutputString + ); + +/** + Get the supported width for a particular op-code + + @param Statement The FORM_BROWSER_STATEMENT structure passed in. + @param Handle The handle in the HII database being used + + @return Returns the number of CHAR16 characters that is support. + +**/ +UINT16 +GetWidth ( + IN FORM_BROWSER_STATEMENT *Statement, + IN EFI_HII_HANDLE Handle + ); + +/** + Concatenate a narrow string to another string. + + @param Destination The destination string. + @param Source The source string. The string to be concatenated. + to the end of Destination. + +**/ +VOID +NewStrCat ( + IN OUT CHAR16 *Destination, + IN CHAR16 *Source + ); + +/** + Wait for a key to be pressed by user. + + @param Key The key which is pressed by user. + + @retval EFI_SUCCESS The function always completed successfully. + +**/ +EFI_STATUS +WaitForKeyStroke ( + OUT EFI_INPUT_KEY *Key + ); + +/** + Reset stack pointer to begin of the stack. + +**/ +VOID +ResetScopeStack ( + VOID + ); + +/** + Push the expression options onto the Stack. + + @param Pointer Pointer to the current expression. + @param Level Which type this expression belong to. Form, + statement or option? + + @retval EFI_SUCCESS The value was pushed onto the stack. + @retval EFI_OUT_OF_RESOURCES There is not enough system memory to grow the stack. + +**/ +EFI_STATUS +PushConditionalExpression ( + IN FORM_EXPRESSION *Pointer, + IN EXPRESS_LEVEL Level + ); + +/** + Pop the expression options from the Stack + + @param Level Which type this expression belong to. Form, + statement or option? + + @retval EFI_SUCCESS The value was pushed onto the stack. + @retval EFI_OUT_OF_RESOURCES There is not enough system memory to grow the stack. + +**/ +EFI_STATUS +PopConditionalExpression ( + IN EXPRESS_LEVEL Level + ); + +/** + Get the expression Buffer pointer. + + @param Level Which type this expression belong to. Form, + statement or option? + + @retval The start pointer of the expression buffer or NULL. + +**/ +FORM_EXPRESSION ** +GetConditionalExpressionList ( + IN EXPRESS_LEVEL Level + ); + +/** + Get the expression list count. + + @param Level Which type this expression belong to. Form, + statement or option? + + @retval >=0 The expression count + @retval -1 Input parameter error. + +**/ +INTN +GetConditionalExpressionCount ( + IN EXPRESS_LEVEL Level + ); + +/** + Push an Operand onto the Stack + + @param Operand Operand to push. + + @retval EFI_SUCCESS The value was pushed onto the stack. + @retval EFI_OUT_OF_RESOURCES There is not enough system memory to grow the + stack. + +**/ +EFI_STATUS +PushScope ( + IN UINT8 Operand + ); + +/** + Pop an Operand from the Stack + + @param Operand Operand to pop. + + @retval EFI_SUCCESS The value was pushed onto the stack. + @retval EFI_OUT_OF_RESOURCES There is not enough system memory to grow the + stack. + +**/ +EFI_STATUS +PopScope ( + OUT UINT8 *Operand + ); + +/** + Reset stack pointer to begin of the stack. + +**/ +VOID +ResetCurrentExpressionStack ( + VOID + ); + +/** + Push current expression onto the Stack + + @param Pointer Pointer to current expression. + + @retval EFI_SUCCESS The value was pushed onto the stack. + @retval EFI_OUT_OF_RESOURCES There is not enough system memory to grow the stack. + +**/ +EFI_STATUS +PushCurrentExpression ( + IN VOID *Pointer + ); + +/** + Pop current expression from the Stack + + @param Pointer Pointer to current expression to be pop. + + @retval EFI_SUCCESS The value was pushed onto the stack. + @retval EFI_OUT_OF_RESOURCES There is not enough system memory to grow the stack. + +**/ +EFI_STATUS +PopCurrentExpression ( + OUT VOID **Pointer + ); + +/** + Reset stack pointer to begin of the stack. + +**/ +VOID +ResetMapExpressionListStack ( + VOID + ); + +/** + Push the list of map expression onto the Stack + + @param Pointer Pointer to the list of map expression to be pushed. + + @retval EFI_SUCCESS The value was pushed onto the stack. + @retval EFI_OUT_OF_RESOURCES There is not enough system memory to grow the stack. + +**/ +EFI_STATUS +PushMapExpressionList ( + IN VOID *Pointer + ); + +/** + Pop the list of map expression from the Stack + + @param Pointer Pointer to the list of map expression to be pop. + + @retval EFI_SUCCESS The value was pushed onto the stack. + @retval EFI_OUT_OF_RESOURCES There is not enough system memory to grow the stack. + +**/ +EFI_STATUS +PopMapExpressionList ( + OUT VOID **Pointer + ); + +/** + Get Form given its FormId. + + @param FormSet The formset which contains this form. + @param FormId Id of this form. + + @retval Pointer The form. + @retval NULL Specified Form is not found in the formset. + +**/ +FORM_BROWSER_FORM * +IdToForm ( + IN FORM_BROWSER_FORMSET *FormSet, + IN UINT16 FormId + ); + +/** + Search a Question in Formset scope using its QuestionId. + + @param FormSet The formset which contains this form. + @param Form The form which contains this Question. + @param QuestionId Id of this Question. + + @retval Pointer The Question. + @retval NULL Specified Question not found in the form. + +**/ +FORM_BROWSER_STATEMENT * +IdToQuestion ( + IN FORM_BROWSER_FORMSET *FormSet, + IN FORM_BROWSER_FORM *Form, + IN UINT16 QuestionId + ); + +/** + Zero extend integer/boolean/date/time to UINT64 for comparing. + + @param Value HII Value to be converted. + +**/ +VOID +ExtendValueToU64 ( + IN EFI_HII_VALUE *Value + ); + +/** + Compare two Hii value. + + @param Value1 Expression value to compare on left-hand. + @param Value2 Expression value to compare on right-hand. + @param Result Return value after compare. + retval 0 Two operators equal. + return Positive value if Value1 is greater than Value2. + retval Negative value if Value1 is less than Value2. + @param HiiHandle Only required for string compare. + + @retval other Could not perform compare on two values. + @retval EFI_SUCCESS Compare the value success. + +**/ +EFI_STATUS +CompareHiiValue ( + IN EFI_HII_VALUE *Value1, + IN EFI_HII_VALUE *Value2, + OUT INTN *Result, + IN EFI_HII_HANDLE HiiHandle OPTIONAL + ); + +/** + Evaluate the result of a HII expression + + If Expression is NULL, then ASSERT. + + @param FormSet FormSet associated with this expression. + @param Form Form associated with this expression. + @param Expression Expression to be evaluated. + + @retval EFI_SUCCESS The expression evaluated successfuly + @retval EFI_NOT_FOUND The Question which referenced by a QuestionId + could not be found. + @retval EFI_OUT_OF_RESOURCES There is not enough system memory to grow the + stack. + @retval EFI_ACCESS_DENIED The pop operation underflowed the stack + @retval EFI_INVALID_PARAMETER Syntax error with the Expression + +**/ +EFI_STATUS +EvaluateExpression ( + IN FORM_BROWSER_FORMSET *FormSet, + IN FORM_BROWSER_FORM *Form, + IN OUT FORM_EXPRESSION *Expression + ); + +/** + Return the result of the expression list. Check the expression list and + return the highest priority express result. + Priority: DisableIf > SuppressIf > GrayOutIf > FALSE + + @param ExpList The input expression list. + @param Evaluate Whether need to evaluate the expression first. + @param FormSet FormSet associated with this expression. Only + needed when Evaluate is TRUE + @param Form Form associated with this expression. Only + needed when Evaluate is TRUE + + @retval EXPRESS_RESULT Return the higher priority express result. + DisableIf > SuppressIf > GrayOutIf > FALSE + +**/ +EXPRESS_RESULT +EvaluateExpressionList ( + IN FORM_EXPRESSION_LIST *ExpList, + IN BOOLEAN Evaluate, + IN FORM_BROWSER_FORMSET *FormSet, OPTIONAL + IN FORM_BROWSER_FORM *Form OPTIONAL + ); + +#endif // _UI_H diff --git a/Nt32Pkg/Nt32Pkg.dsc b/Nt32Pkg/Nt32Pkg.dsc index 507e7ed0e1..cfcfc4234d 100644 --- a/Nt32Pkg/Nt32Pkg.dsc +++ b/Nt32Pkg/Nt32Pkg.dsc @@ -102,7 +102,6 @@ DpcLib|MdeModulePkg/Library/DxeDpcLib/DxeDpcLib.inf OemHookStatusCodeLib|MdeModulePkg/Library/OemHookStatusCodeLibNull/OemHookStatusCodeLibNull.inf GenericBdsLib|IntelFrameworkModulePkg/Library/GenericBdsLib/GenericBdsLib.inf - CustomizedDisplayLib|MdeModulePkg/Library/CustomizedDisplayLib/CustomizedDisplayLib.inf SecurityManagementLib|MdeModulePkg/Library/DxeSecurityManagementLib/DxeSecurityManagementLib.inf TimerLib|MdePkg/Library/BaseTimerLibNullTemplate/BaseTimerLibNullTemplate.inf SerialPortLib|MdePkg/Library/BaseSerialPortLibNull/BaseSerialPortLibNull.inf @@ -407,7 +406,6 @@ IntelFrameworkModulePkg/Universal/BdsDxe/BdsDxe.inf MdeModulePkg/Universal/HiiDatabaseDxe/HiiDatabaseDxe.inf - MdeModulePkg/Universal/DisplayEngineDxe/DisplayEngineDxe.inf MdeModulePkg/Universal/SetupBrowserDxe/SetupBrowserDxe.inf MdeModulePkg/Universal/PrintDxe/PrintDxe.inf MdeModulePkg/Universal/DriverSampleDxe/DriverSampleDxe.inf { diff --git a/Nt32Pkg/Nt32Pkg.fdf b/Nt32Pkg/Nt32Pkg.fdf index 7315d432fa..2b8a8e76d3 100644 --- a/Nt32Pkg/Nt32Pkg.fdf +++ b/Nt32Pkg/Nt32Pkg.fdf @@ -233,7 +233,6 @@ INF MdeModulePkg/Universal/Console/TerminalDxe/TerminalDxe.inf INF MdeModulePkg/Universal/DevicePathDxe/DevicePathDxe.inf INF MdeModulePkg/Universal/Disk/DiskIoDxe/DiskIoDxe.inf INF MdeModulePkg/Universal/Disk/PartitionDxe/PartitionDxe.inf -INF MdeModulePkg/Universal/DisplayEngineDxe/DisplayEngineDxe.inf INF MdeModulePkg/Universal/SetupBrowserDxe/SetupBrowserDxe.inf INF MdeModulePkg/Universal/PrintDxe/PrintDxe.inf INF RuleOverride = TIANOCOMPRESSED MdeModulePkg/Universal/Disk/UnicodeCollation/EnglishDxe/EnglishDxe.inf diff --git a/OvmfPkg/OvmfPkgIa32.dsc b/OvmfPkg/OvmfPkgIa32.dsc index 28b1815c70..f732703fdb 100644 --- a/OvmfPkg/OvmfPkgIa32.dsc +++ b/OvmfPkg/OvmfPkgIa32.dsc @@ -100,7 +100,6 @@ VirtioLib|OvmfPkg/Library/VirtioLib/VirtioLib.inf LoadLinuxLib|OvmfPkg/Library/LoadLinuxLib/LoadLinuxLib.inf LockBoxLib|MdeModulePkg/Library/LockBoxNullLib/LockBoxNullLib.inf - CustomizedDisplayLib|MdeModulePkg/Library/CustomizedDisplayLib/CustomizedDisplayLib.inf !ifdef $(SOURCE_DEBUG_ENABLE) PeCoffExtraActionLib|SourceLevelDebugPkg/Library/PeCoffExtraActionLibDebug/PeCoffExtraActionLibDebug.inf @@ -436,7 +435,6 @@ PcAtChipsetPkg/Bus/Pci/IdeControllerDxe/IdeControllerDxe.inf MdeModulePkg/Universal/HiiDatabaseDxe/HiiDatabaseDxe.inf MdeModulePkg/Universal/SetupBrowserDxe/SetupBrowserDxe.inf - MdeModulePkg/Universal/DisplayEngineDxe/DisplayEngineDxe.inf MdeModulePkg/Universal/MemoryTest/NullMemoryTestDxe/NullMemoryTestDxe.inf OvmfPkg/QemuVideoDxe/QemuVideoDxe.inf { diff --git a/OvmfPkg/OvmfPkgIa32.fdf b/OvmfPkg/OvmfPkgIa32.fdf index 7acd16717e..be6ca885b9 100644 --- a/OvmfPkg/OvmfPkgIa32.fdf +++ b/OvmfPkg/OvmfPkgIa32.fdf @@ -211,7 +211,6 @@ INF IntelFrameworkModulePkg/Bus/Pci/IdeBusDxe/IdeBusDxe.inf INF PcAtChipsetPkg/Bus/Pci/IdeControllerDxe/IdeControllerDxe.inf INF MdeModulePkg/Universal/HiiDatabaseDxe/HiiDatabaseDxe.inf INF MdeModulePkg/Universal/SetupBrowserDxe/SetupBrowserDxe.inf -INF MdeModulePkg/Universal/DisplayEngineDxe/DisplayEngineDxe.inf INF MdeModulePkg/Universal/MemoryTest/NullMemoryTestDxe/NullMemoryTestDxe.inf INF PcAtChipsetPkg/IsaAcpiDxe/IsaAcpi.inf diff --git a/OvmfPkg/OvmfPkgIa32X64.dsc b/OvmfPkg/OvmfPkgIa32X64.dsc index 2b35027b6a..dcfb95aa32 100644 --- a/OvmfPkg/OvmfPkgIa32X64.dsc +++ b/OvmfPkg/OvmfPkgIa32X64.dsc @@ -105,7 +105,6 @@ VirtioLib|OvmfPkg/Library/VirtioLib/VirtioLib.inf LoadLinuxLib|OvmfPkg/Library/LoadLinuxLib/LoadLinuxLib.inf LockBoxLib|MdeModulePkg/Library/LockBoxNullLib/LockBoxNullLib.inf - CustomizedDisplayLib|MdeModulePkg/Library/CustomizedDisplayLib/CustomizedDisplayLib.inf !ifdef $(SOURCE_DEBUG_ENABLE) PeCoffExtraActionLib|SourceLevelDebugPkg/Library/PeCoffExtraActionLibDebug/PeCoffExtraActionLibDebug.inf @@ -448,7 +447,6 @@ PcAtChipsetPkg/Bus/Pci/IdeControllerDxe/IdeControllerDxe.inf MdeModulePkg/Universal/HiiDatabaseDxe/HiiDatabaseDxe.inf MdeModulePkg/Universal/SetupBrowserDxe/SetupBrowserDxe.inf - MdeModulePkg/Universal/DisplayEngineDxe/DisplayEngineDxe.inf MdeModulePkg/Universal/MemoryTest/NullMemoryTestDxe/NullMemoryTestDxe.inf OvmfPkg/QemuVideoDxe/QemuVideoDxe.inf { diff --git a/OvmfPkg/OvmfPkgIa32X64.fdf b/OvmfPkg/OvmfPkgIa32X64.fdf index 2bd31f6b82..fe77a3a3de 100644 --- a/OvmfPkg/OvmfPkgIa32X64.fdf +++ b/OvmfPkg/OvmfPkgIa32X64.fdf @@ -212,7 +212,6 @@ INF IntelFrameworkModulePkg/Bus/Pci/IdeBusDxe/IdeBusDxe.inf INF PcAtChipsetPkg/Bus/Pci/IdeControllerDxe/IdeControllerDxe.inf INF MdeModulePkg/Universal/HiiDatabaseDxe/HiiDatabaseDxe.inf INF MdeModulePkg/Universal/SetupBrowserDxe/SetupBrowserDxe.inf -INF MdeModulePkg/Universal/DisplayEngineDxe/DisplayEngineDxe.inf INF MdeModulePkg/Universal/MemoryTest/NullMemoryTestDxe/NullMemoryTestDxe.inf INF PcAtChipsetPkg/IsaAcpiDxe/IsaAcpi.inf diff --git a/OvmfPkg/OvmfPkgX64.dsc b/OvmfPkg/OvmfPkgX64.dsc index cd09beb3b4..89ce44e6d2 100644 --- a/OvmfPkg/OvmfPkgX64.dsc +++ b/OvmfPkg/OvmfPkgX64.dsc @@ -105,7 +105,6 @@ VirtioLib|OvmfPkg/Library/VirtioLib/VirtioLib.inf LoadLinuxLib|OvmfPkg/Library/LoadLinuxLib/LoadLinuxLib.inf LockBoxLib|MdeModulePkg/Library/LockBoxNullLib/LockBoxNullLib.inf - CustomizedDisplayLib|MdeModulePkg/Library/CustomizedDisplayLib/CustomizedDisplayLib.inf !ifdef $(SOURCE_DEBUG_ENABLE) PeCoffExtraActionLib|SourceLevelDebugPkg/Library/PeCoffExtraActionLibDebug/PeCoffExtraActionLibDebug.inf @@ -441,7 +440,6 @@ PcAtChipsetPkg/Bus/Pci/IdeControllerDxe/IdeControllerDxe.inf MdeModulePkg/Universal/HiiDatabaseDxe/HiiDatabaseDxe.inf MdeModulePkg/Universal/SetupBrowserDxe/SetupBrowserDxe.inf - MdeModulePkg/Universal/DisplayEngineDxe/DisplayEngineDxe.inf MdeModulePkg/Universal/MemoryTest/NullMemoryTestDxe/NullMemoryTestDxe.inf OvmfPkg/QemuVideoDxe/QemuVideoDxe.inf { diff --git a/OvmfPkg/OvmfPkgX64.fdf b/OvmfPkg/OvmfPkgX64.fdf index 7db09cad55..abeedefd85 100644 --- a/OvmfPkg/OvmfPkgX64.fdf +++ b/OvmfPkg/OvmfPkgX64.fdf @@ -211,7 +211,6 @@ INF IntelFrameworkModulePkg/Bus/Pci/IdeBusDxe/IdeBusDxe.inf INF PcAtChipsetPkg/Bus/Pci/IdeControllerDxe/IdeControllerDxe.inf INF MdeModulePkg/Universal/HiiDatabaseDxe/HiiDatabaseDxe.inf INF MdeModulePkg/Universal/SetupBrowserDxe/SetupBrowserDxe.inf -INF MdeModulePkg/Universal/DisplayEngineDxe/DisplayEngineDxe.inf INF MdeModulePkg/Universal/MemoryTest/NullMemoryTestDxe/NullMemoryTestDxe.inf INF PcAtChipsetPkg/IsaAcpiDxe/IsaAcpi.inf