summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorvanjeff <vanjeff>2013-09-10 05:48:30 +0000
committervanjeff <vanjeff@6f19259b-4bc3-4df7-8a09-765794883524>2013-09-10 05:48:30 +0000
commitc9fcba3dca0918c0776a79b5697ab07968321aaf (patch)
tree5b6392141e26745c2c4e6ee76dcf4f95aa5fcfa6
parent07985bb01e0cacf5b096bfadbba10f3daa75d148 (diff)
downloadedk2-c9fcba3dca0918c0776a79b5697ab07968321aaf.zip
edk2-c9fcba3dca0918c0776a79b5697ab07968321aaf.tar.gz
edk2-c9fcba3dca0918c0776a79b5697ab07968321aaf.tar.bz2
Sync patches r14112, r14540 and r14543 from main trunk.
1. Based on the feature PCD value, browser will decide whether to gray out the read only menu. 2. Update Browser to provide the customization possibilities. 3. Refine the code logic for browser and display engine. git-svn-id: https://svn.code.sf.net/p/edk2/code/branches/UDK2010.SR1@14638 6f19259b-4bc3-4df7-8a09-765794883524
-rw-r--r--MdeModulePkg/Include/Library/CustomizedDisplayLib.h356
-rw-r--r--MdeModulePkg/Include/Protocol/DisplayProtocol.h350
-rw-r--r--MdeModulePkg/Include/Protocol/FormBrowserEx2.h90
-rw-r--r--MdeModulePkg/Library/CustomizedDisplayLib/Colors.h (renamed from MdeModulePkg/Universal/SetupBrowserDxe/Colors.h)0
-rw-r--r--MdeModulePkg/Library/CustomizedDisplayLib/CustomizedDisplayLib.c921
-rw-r--r--MdeModulePkg/Library/CustomizedDisplayLib/CustomizedDisplayLib.inf74
-rw-r--r--MdeModulePkg/Library/CustomizedDisplayLib/CustomizedDisplayLib.unibin0 -> 7256 bytes
-rw-r--r--MdeModulePkg/Library/CustomizedDisplayLib/CustomizedDisplayLibInternal.c914
-rw-r--r--MdeModulePkg/Library/CustomizedDisplayLib/CustomizedDisplayLibInternal.h295
-rw-r--r--MdeModulePkg/MdeModulePkg.dec17
-rw-r--r--MdeModulePkg/MdeModulePkg.dsc4
-rw-r--r--MdeModulePkg/Universal/DisplayEngineDxe/DisplayEngineDxe.inf66
-rw-r--r--MdeModulePkg/Universal/DisplayEngineDxe/FormDisplay.c3255
-rw-r--r--MdeModulePkg/Universal/DisplayEngineDxe/FormDisplay.h589
-rw-r--r--MdeModulePkg/Universal/DisplayEngineDxe/FormDisplayStr.uni (renamed from MdeModulePkg/Universal/SetupBrowserDxe/SetupBrowserStr.uni)bin14784 -> 8660 bytes
-rw-r--r--MdeModulePkg/Universal/DisplayEngineDxe/InputHandler.c (renamed from MdeModulePkg/Universal/SetupBrowserDxe/InputHandler.c)600
-rw-r--r--MdeModulePkg/Universal/DisplayEngineDxe/ProcessOptions.c1286
-rw-r--r--MdeModulePkg/Universal/SetupBrowserDxe/Expression.c8
-rw-r--r--MdeModulePkg/Universal/SetupBrowserDxe/Expression.h265
-rw-r--r--MdeModulePkg/Universal/SetupBrowserDxe/IfrParse.c71
-rw-r--r--MdeModulePkg/Universal/SetupBrowserDxe/Presentation.c2426
-rw-r--r--MdeModulePkg/Universal/SetupBrowserDxe/Print.c272
-rw-r--r--MdeModulePkg/Universal/SetupBrowserDxe/ProcessOptions.c1042
-rw-r--r--MdeModulePkg/Universal/SetupBrowserDxe/Setup.c2322
-rw-r--r--MdeModulePkg/Universal/SetupBrowserDxe/Setup.h821
-rw-r--r--MdeModulePkg/Universal/SetupBrowserDxe/SetupBrowserDxe.inf25
-rw-r--r--MdeModulePkg/Universal/SetupBrowserDxe/Ui.c4011
-rw-r--r--MdeModulePkg/Universal/SetupBrowserDxe/Ui.h1031
28 files changed, 12329 insertions, 8782 deletions
diff --git a/MdeModulePkg/Include/Library/CustomizedDisplayLib.h b/MdeModulePkg/Include/Library/CustomizedDisplayLib.h
new file mode 100644
index 0000000..31e1091
--- /dev/null
+++ b/MdeModulePkg/Include/Library/CustomizedDisplayLib.h
@@ -0,0 +1,356 @@
+/** @file
+ This library class defines a set of interfaces to customize Display module
+
+Copyright (c) 2013, Intel Corporation. All rights reserved.<BR>
+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 <Protocol/DisplayProtocol.h>
+
+/**
++------------------------------------------------------------------------------+
+| Setup Page |
++------------------------------------------------------------------------------+
+
+Statement
+Statement
+Statement
+
+
+
+
+
++------------------------------------------------------------------------------+
+| F9=Reset to Defaults F10=Save |
+| ^"=Move Highlight <Spacebar> 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
new file mode 100644
index 0000000..d4f0deb
--- /dev/null
+++ b/MdeModulePkg/Include/Protocol/DisplayProtocol.h
@@ -0,0 +1,350 @@
+/** @file
+ FormDiplay protocol to show Form
+
+Copyright (c) 2013, Intel Corporation. All rights reserved.<BR>
+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 <Protocol/FormBrowser2.h>
+
+#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
new file mode 100644
index 0000000..105ac03
--- /dev/null
+++ b/MdeModulePkg/Include/Protocol/FormBrowserEx2.h
@@ -0,0 +1,90 @@
+/** @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.<BR>
+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 <Protocol/FormBrowserEx.h>
+
+#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/Universal/SetupBrowserDxe/Colors.h b/MdeModulePkg/Library/CustomizedDisplayLib/Colors.h
index 2db8b99..2db8b99 100644
--- a/MdeModulePkg/Universal/SetupBrowserDxe/Colors.h
+++ b/MdeModulePkg/Library/CustomizedDisplayLib/Colors.h
diff --git a/MdeModulePkg/Library/CustomizedDisplayLib/CustomizedDisplayLib.c b/MdeModulePkg/Library/CustomizedDisplayLib/CustomizedDisplayLib.c
new file mode 100644
index 0000000..aa28146
--- /dev/null
+++ b/MdeModulePkg/Library/CustomizedDisplayLib/CustomizedDisplayLib.c
@@ -0,0 +1,921 @@
+/** @file
+
+ This library class defines a set of interfaces to customize Display module
+
+Copyright (c) 2013, Intel Corporation. All rights reserved.<BR>
+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 <Spacebar> 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
new file mode 100644
index 0000000..ade45b6
--- /dev/null
+++ b/MdeModulePkg/Library/CustomizedDisplayLib/CustomizedDisplayLib.inf
@@ -0,0 +1,74 @@
+##
+# 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.<BR>
+# 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
new file mode 100644
index 0000000..18a5c3b
--- /dev/null
+++ b/MdeModulePkg/Library/CustomizedDisplayLib/CustomizedDisplayLib.uni
Binary files differ
diff --git a/MdeModulePkg/Library/CustomizedDisplayLib/CustomizedDisplayLibInternal.c b/MdeModulePkg/Library/CustomizedDisplayLib/CustomizedDisplayLibInternal.c
new file mode 100644
index 0000000..b6b4055
--- /dev/null
+++ b/MdeModulePkg/Library/CustomizedDisplayLib/CustomizedDisplayLibInternal.c
@@ -0,0 +1,914 @@
+/** @file
+
+ This library class defines a set of interfaces to customize Display module
+
+Copyright (c) 2013, Intel Corporation. All rights reserved.<BR>
+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
new file mode 100644
index 0000000..ccbd45f
--- /dev/null
+++ b/MdeModulePkg/Library/CustomizedDisplayLib/CustomizedDisplayLibInternal.h
@@ -0,0 +1,295 @@
+/** @file
+
+ This library class defines a set of interfaces to customize Display module
+
+Copyright (c) 2013, Intel Corporation. All rights reserved.<BR>
+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 <PiDxe.h>
+
+#include <Protocol/SimpleTextOut.h>
+#include <Protocol/SimpleTextIn.h>
+#include <Protocol/FormBrowser2.h>
+#include <Protocol/FormBrowserEx2.h>
+#include <Protocol/DisplayProtocol.h>
+#include <Protocol/DevicePath.h>
+#include <Protocol/UnicodeCollation.h>
+#include <Protocol/HiiConfigAccess.h>
+#include <Protocol/HiiConfigRouting.h>
+#include <Protocol/HiiDatabase.h>
+#include <Protocol/HiiString.h>
+#include <Protocol/UserManager.h>
+#include <Protocol/DevicePathFromText.h>
+
+#include <Guid/MdeModuleHii.h>
+#include <Guid/HiiPlatformSetupFormset.h>
+#include <Guid/HiiFormMapMethodGuid.h>
+
+#include <Library/PrintLib.h>
+#include <Library/DebugLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/UefiRuntimeServicesTableLib.h>
+#include <Library/UefiDriverEntryPoint.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/BaseLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/HiiLib.h>
+#include <Library/PcdLib.h>
+#include <Library/DevicePathLib.h>
+#include <Library/CustomizedDisplayLib.h>
+
+#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 ce77f02..078086e 100644
--- a/MdeModulePkg/MdeModulePkg.dec
+++ b/MdeModulePkg/MdeModulePkg.dec
@@ -4,7 +4,7 @@
# It also provides the defintions(including PPIs/PROTOCOLs/GUIDs and library classes)
# and libraries instances, which are used for those modules.
#
-# Copyright (c) 2007 - 2012, Intel Corporation. All rights reserved.<BR>
+# Copyright (c) 2007 - 2013, Intel Corporation. All rights reserved.<BR>
# 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
@@ -94,6 +94,10 @@
#
LockBoxLib|Include/Library/LockBoxLib.h
+ ## @libraryclass Provides platform specific display interface.
+ #
+ CustomizedDisplayLib|Include/Library/CustomizedDisplayLib.h
+
[Guids]
## MdeModule package token space guid
# Include/Guid/MdeModulePkgTokenSpace.h
@@ -345,6 +349,12 @@
## 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
@@ -450,6 +460,11 @@
# If FALSE, TEXT statement will be set to GrayOut only when GrayOut condition is TRUE.
gEfiMdeModulePkgTokenSpaceGuid.PcdBrowserGrayOutTextStatement|FALSE|BOOLEAN|0x0001004f
+ ## This PCD specifies whether unselectable menu should be gray out in HII Form Browser.
+ # If TRUE, the unselectable menu will be set to GrayOut.
+ # If FALSE, the menu will be show as normal menu entry even if it is not selectable.
+ gEfiMdeModulePkgTokenSpaceGuid.PcdBrowerGrayOutReadOnlyMenu|FALSE|BOOLEAN|0x00010070
+
## If TRUE, recovery from IDE disk will be supported.
gEfiMdeModulePkgTokenSpaceGuid.PcdRecoveryOnIdeDisk|TRUE|BOOLEAN|0x00010060
diff --git a/MdeModulePkg/MdeModulePkg.dsc b/MdeModulePkg/MdeModulePkg.dsc
index 215600d..7a00a5d 100644
--- a/MdeModulePkg/MdeModulePkg.dsc
+++ b/MdeModulePkg/MdeModulePkg.dsc
@@ -1,7 +1,7 @@
## @file
# EFI/PI Reference Module Package for All Architectures
#
-# Copyright (c) 2007 - 2011, Intel Corporation. All rights reserved.<BR>
+# Copyright (c) 2007 - 2013, Intel Corporation. All rights reserved.<BR>
#
# This program and the accompanying materials
# are licensed and made available under the terms and conditions of the BSD License
@@ -76,6 +76,7 @@
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
#
@@ -291,6 +292,7 @@
MdeModulePkg/Universal/SecurityStubDxe/SecurityStubDxe.inf
MdeModulePkg/Universal/SetupBrowserDxe/SetupBrowserDxe.inf
+ MdeModulePkg/Universal/DisplayEngineDxe/DisplayEngineDxe.inf
MdeModulePkg/Application/VariableInfo/VariableInfo.inf
MdeModulePkg/Universal/Variable/Pei/VariablePei.inf
MdeModulePkg/Universal/WatchdogTimerDxe/WatchdogTimer.inf
diff --git a/MdeModulePkg/Universal/DisplayEngineDxe/DisplayEngineDxe.inf b/MdeModulePkg/Universal/DisplayEngineDxe/DisplayEngineDxe.inf
new file mode 100644
index 0000000..323fcad
--- /dev/null
+++ b/MdeModulePkg/Universal/DisplayEngineDxe/DisplayEngineDxe.inf
@@ -0,0 +1,66 @@
+## @file
+# The DXE driver produces FORM BROWSER protocols defined in UEFI HII 2.1 specificatin.
+#
+# Copyright (c) 2007 - 2013, Intel Corporation. All rights reserved.<BR>
+#
+# 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
new file mode 100644
index 0000000..a07cc75
--- /dev/null
+++ b/MdeModulePkg/Universal/DisplayEngineDxe/FormDisplay.c
@@ -0,0 +1,3255 @@
+/** @file
+Entry and initialization module for the browser.
+
+Copyright (c) 2007 - 2013, Intel Corporation. All rights reserved.<BR>
+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
new file mode 100644
index 0000000..45bcadc
--- /dev/null
+++ b/MdeModulePkg/Universal/DisplayEngineDxe/FormDisplay.h
@@ -0,0 +1,589 @@
+/** @file
+ FormDiplay protocol to show Form
+
+Copyright (c) 2013, Intel Corporation. All rights reserved.<BR>
+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 <Library/UefiBootServicesTableLib.h>
+#include <Library/DebugLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/BaseLib.h>
+#include <Library/HiiLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/PrintLib.h>
+#include <Library/CustomizedDisplayLib.h>
+
+#include <Protocol/FormBrowserEx2.h>
+#include <Protocol/SimpleTextIn.h>
+#include <Protocol/DisplayProtocol.h>
+
+#include <Guid/MdeModuleHii.h>
+
+//
+// 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/SetupBrowserDxe/SetupBrowserStr.uni b/MdeModulePkg/Universal/DisplayEngineDxe/FormDisplayStr.uni
index bb6414d..0ee7f46 100644
--- a/MdeModulePkg/Universal/SetupBrowserDxe/SetupBrowserStr.uni
+++ b/MdeModulePkg/Universal/DisplayEngineDxe/FormDisplayStr.uni
Binary files differ
diff --git a/MdeModulePkg/Universal/SetupBrowserDxe/InputHandler.c b/MdeModulePkg/Universal/DisplayEngineDxe/InputHandler.c
index e5257bc..a58e12f 100644
--- a/MdeModulePkg/Universal/SetupBrowserDxe/InputHandler.c
+++ b/MdeModulePkg/Universal/DisplayEngineDxe/InputHandler.c
@@ -12,8 +12,38 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
**/
-#include "Setup.h"
+#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.
@@ -52,11 +82,11 @@ ReadString (
BOOLEAN CursorVisible;
UINTN Minimum;
UINTN Maximum;
- FORM_BROWSER_STATEMENT *Question;
+ FORM_DISPLAY_ENGINE_STATEMENT *Question;
BOOLEAN IsPassword;
- DimensionsWidth = gScreenDimensions.RightColumn - gScreenDimensions.LeftColumn;
- DimensionsHeight = gScreenDimensions.BottomRow - gScreenDimensions.TopRow;
+ DimensionsWidth = gStatementDimensions.RightColumn - gStatementDimensions.LeftColumn;
+ DimensionsHeight = gStatementDimensions.BottomRow - gStatementDimensions.TopRow;
NullCharacter = CHAR_NULL;
ScreenSize = GetStringWidth (Prompt) / sizeof (CHAR16);
@@ -64,10 +94,9 @@ ReadString (
Space[1] = CHAR_NULL;
Question = MenuOption->ThisTag;
- Minimum = (UINTN) Question->Minimum;
- Maximum = (UINTN) Question->Maximum;
+ GetFieldFromOp(Question->OpCode, &Minimum, &Maximum);
- if (Question->Operand == EFI_IFR_PASSWORD_OP) {
+ if (Question->OpCode->OpCode == EFI_IFR_PASSWORD_OP) {
IsPassword = TRUE;
} else {
IsPassword = FALSE;
@@ -87,14 +116,14 @@ ReadString (
BufferedString = AllocateZeroPool (ScreenSize * 2);
ASSERT (BufferedString);
- Start = (DimensionsWidth - ScreenSize - 2) / 2 + gScreenDimensions.LeftColumn + 1;
- Top = ((DimensionsHeight - 6) / 2) + gScreenDimensions.TopRow - 1;
+ 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;
@@ -122,7 +151,7 @@ ReadString (
BufferedString[Count] = StringPtr[Index];
if (IsPassword) {
- PrintChar (L'*');
+ PrintCharAt ((UINTN)-1, (UINTN)-1, L'*');
}
}
@@ -181,7 +210,7 @@ ReadString (
// 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);
+ CreateDialog (&Key, &NullCharacter, gMiniString, gPressEnter, &NullCharacter, NULL);
} while (Key.UnicodeChar != CHAR_CARRIAGE_RETURN);
FreePool (TempString);
@@ -258,7 +287,7 @@ ReadString (
BufferedString[Count] = StringPtr[Index];
if (IsPassword) {
- PrintChar (L'*');
+ PrintCharAt ((UINTN)-1, (UINTN)-1, L'*');
}
}
@@ -279,12 +308,12 @@ ReadString (
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 QuestionValue Pointer to current question.
@param Sequence The sequence of the field in the question.
**/
VOID
AdjustQuestionValue (
- IN FORM_BROWSER_STATEMENT *Question,
+ IN EFI_HII_VALUE *QuestionValue,
IN UINT8 Sequence
)
{
@@ -293,12 +322,8 @@ AdjustQuestionValue (
UINT8 Maximum;
UINT8 Minimum;
- if (Question->Operand != EFI_IFR_DATE_OP) {
- return;
- }
-
- Month = Question->HiiValue.Value.date.Month;
- Year = Question->HiiValue.Value.date.Year;
+ Month = QuestionValue->Value.date.Month;
+ Year = QuestionValue->Value.date.Year;
Minimum = 1;
switch (Month) {
@@ -324,8 +349,8 @@ AdjustQuestionValue (
// Change the month area.
//
if (Sequence == 0) {
- if (Question->HiiValue.Value.date.Day > Maximum) {
- Question->HiiValue.Value.date.Day = Maximum;
+ if (QuestionValue->Value.date.Day > Maximum) {
+ QuestionValue->Value.date.Day = Maximum;
}
}
@@ -333,16 +358,76 @@ AdjustQuestionValue (
// Change the Year area.
//
if (Sequence == 2) {
- if (Question->HiiValue.Value.date.Day > Maximum) {
- Question->HiiValue.Value.date.Day = Minimum;
+ 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 Selection Pointer to current selection.
@param MenuOption Pointer to the current input menu.
@retval EFI_SUCCESS If numerical input is read successfully
@@ -351,7 +436,6 @@ AdjustQuestionValue (
**/
EFI_STATUS
GetNumericInput (
- IN UI_MENU_SELECTION *Selection,
IN UI_MENU_OPTION *MenuOption
)
{
@@ -375,9 +459,9 @@ GetNumericInput (
UINT8 Digital;
EFI_INPUT_KEY Key;
EFI_HII_VALUE *QuestionValue;
- FORM_BROWSER_FORM *Form;
- FORM_BROWSER_FORMSET *FormSet;
- FORM_BROWSER_STATEMENT *Question;
+ FORM_DISPLAY_ENGINE_STATEMENT *Question;
+ EFI_IFR_NUMERIC *NumericOp;
+ UINT16 StorageWidth;
Column = MenuOption->OptCol;
Row = MenuOption->Row;
@@ -385,14 +469,13 @@ GetNumericInput (
Count = 0;
InputWidth = 0;
Digital = 0;
+ StorageWidth = 0;
+ Minimum = 0;
+ Maximum = 0;
+ NumericOp = NULL;
- FormSet = Selection->FormSet;
- Form = Selection->Form;
Question = MenuOption->ThisTag;
- QuestionValue = &Question->HiiValue;
- Step = Question->Step;
- Minimum = Question->Minimum;
- Maximum = Question->Maximum;
+ QuestionValue = &Question->CurrentValue;
//
// Only two case, user can enter to this function: Enter and +/- case.
@@ -400,7 +483,7 @@ GetNumericInput (
//
ManualInput = (BOOLEAN)(gDirection == 0 ? TRUE : FALSE);
- if ((Question->Operand == EFI_IFR_DATE_OP) || (Question->Operand == EFI_IFR_TIME_OP)) {
+ if ((Question->OpCode->OpCode == EFI_IFR_DATE_OP) || (Question->OpCode->OpCode == EFI_IFR_TIME_OP)) {
DateOrTime = TRUE;
} else {
DateOrTime = FALSE;
@@ -411,7 +494,7 @@ GetNumericInput (
//
EraseLen = 0;
EditValue = 0;
- if (Question->Operand == EFI_IFR_DATE_OP) {
+ if (Question->OpCode->OpCode == EFI_IFR_DATE_OP) {
Step = 1;
Minimum = 1;
@@ -457,7 +540,7 @@ GetNumericInput (
default:
break;
}
- } else if (Question->Operand == EFI_IFR_TIME_OP) {
+ } else if (Question->OpCode->OpCode == EFI_IFR_TIME_OP) {
Step = 1;
Minimum = 0;
@@ -484,18 +567,15 @@ GetNumericInput (
break;
}
} else {
- //
- // Numeric
- //
- EraseLen = gOptionBlockWidth;
+ 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;
- if (Maximum == 0) {
- Maximum = (UINT64) -1;
- }
+ EraseLen = gOptionBlockWidth;
}
- if ((Question->Operand == EFI_IFR_NUMERIC_OP) &&
- ((Question->Flags & EFI_IFR_DISPLAY) == EFI_IFR_DISPLAY_UINT_HEX)) {
+ 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;
@@ -505,11 +585,11 @@ GetNumericInput (
// Enter from "Enter" input, clear the old word showing.
//
if (ManualInput) {
- if (Question->Operand == EFI_IFR_NUMERIC_OP) {
+ if (Question->OpCode->OpCode == EFI_IFR_NUMERIC_OP) {
if (HexInput) {
- InputWidth = Question->StorageWidth * 2;
+ InputWidth = StorageWidth * 2;
} else {
- switch (Question->StorageWidth) {
+ switch (StorageWidth) {
case 1:
InputWidth = 3;
break;
@@ -538,11 +618,11 @@ GetNumericInput (
InputText[InputWidth + 1] = RIGHT_NUMERIC_DELIMITER;
InputText[InputWidth + 2] = L'\0';
- PrintAt (Column, Row, InputText);
+ PrintStringAt (Column, Row, InputText);
Column++;
}
- if (Question->Operand == EFI_IFR_DATE_OP) {
+ if (Question->OpCode->OpCode == EFI_IFR_DATE_OP) {
if (MenuOption->Sequence == 2) {
InputWidth = 4;
} else {
@@ -563,13 +643,13 @@ GetNumericInput (
}
InputText[InputWidth + 2] = L'\0';
- PrintAt (Column, Row, InputText);
+ PrintStringAt (Column, Row, InputText);
if (MenuOption->Sequence == 0) {
Column++;
}
}
- if (Question->Operand == EFI_IFR_TIME_OP) {
+ if (Question->OpCode->OpCode == EFI_IFR_TIME_OP) {
InputWidth = 2;
if (MenuOption->Sequence == 0) {
@@ -586,7 +666,7 @@ GetNumericInput (
}
InputText[InputWidth + 2] = L'\0';
- PrintAt (Column, Row, InputText);
+ PrintStringAt (Column, Row, InputText);
if (MenuOption->Sequence == 0) {
Column++;
}
@@ -654,7 +734,7 @@ TheKey2:
}
ZeroMem (FormattedNumber, 21 * sizeof (CHAR16));
- if (Question->Operand == EFI_IFR_DATE_OP) {
+ if (Question->OpCode->OpCode == EFI_IFR_DATE_OP) {
if (MenuOption->Sequence == 2) {
//
// Year
@@ -674,7 +754,7 @@ TheKey2:
ASSERT (EraseLen >= 1);
FormattedNumber[EraseLen - 1] = DATE_SEPARATOR;
}
- } else if (Question->Operand == EFI_IFR_TIME_OP) {
+ } else if (Question->OpCode->OpCode == EFI_IFR_TIME_OP) {
UnicodeSPrint (FormattedNumber, 21 * sizeof (CHAR16), L"%02d", (UINT8) EditValue);
if (MenuOption->Sequence == 0) {
@@ -689,11 +769,11 @@ TheKey2:
PrintFormattedNumber (Question, FormattedNumber, 21 * sizeof (CHAR16));
}
- gST->ConOut->SetAttribute (gST->ConOut, PcdGet8 (PcdBrowserFieldTextColor) | FIELD_BACKGROUND);
+ gST->ConOut->SetAttribute (gST->ConOut, GetFieldTextColor ());
for (Loop = 0; Loop < EraseLen; Loop++) {
- PrintAt (MenuOption->OptCol + Loop, MenuOption->Row, L" ");
+ PrintStringAt (MenuOption->OptCol + Loop, MenuOption->Row, L" ");
}
- gST->ConOut->SetAttribute (gST->ConOut, PcdGet8 (PcdBrowserFieldTextHighlightColor) | PcdGet8 (PcdBrowserFieldBackgroundHighlightColor));
+ gST->ConOut->SetAttribute (gST->ConOut, GetHighlightTextColor ());
if (MenuOption->Sequence == 0) {
PrintCharAt (MenuOption->OptCol, Row, LEFT_NUMERIC_DELIMITER);
@@ -703,7 +783,7 @@ TheKey2:
PrintStringAt (Column, Row, FormattedNumber);
if (!DateOrTime || MenuOption->Sequence == 2) {
- PrintChar (RIGHT_NUMERIC_DELIMITER);
+ PrintCharAt ((UINTN)-1, (UINTN)-1, RIGHT_NUMERIC_DELIMITER);
}
}
@@ -730,16 +810,18 @@ EnterCarriageReturn:
// Validate input value with Minimum value.
//
if (EditValue < Minimum) {
- UpdateStatusBar (Selection, INPUT_ERROR, Question->QuestionFlags, TRUE);
+ UpdateStatusBar (INPUT_ERROR, TRUE);
break;
} else {
- UpdateStatusBar (Selection, INPUT_ERROR, Question->QuestionFlags, FALSE);
+ UpdateStatusBar (INPUT_ERROR, FALSE);
}
-
+
+ CopyMem (&gUserInput->InputValue, &Question->CurrentValue, sizeof (EFI_HII_VALUE));
+ QuestionValue = &gUserInput->InputValue;
//
// Store Edit value back to Question
//
- if (Question->Operand == EFI_IFR_DATE_OP) {
+ if (Question->OpCode->OpCode == EFI_IFR_DATE_OP) {
switch (MenuOption->Sequence) {
case 0:
QuestionValue->Value.date.Month = (UINT8) EditValue;
@@ -756,7 +838,7 @@ EnterCarriageReturn:
default:
break;
}
- } else if (Question->Operand == EFI_IFR_TIME_OP) {
+ } else if (Question->OpCode->OpCode == EFI_IFR_TIME_OP) {
switch (MenuOption->Sequence) {
case 0:
QuestionValue->Value.time.Hour = (UINT8) EditValue;
@@ -785,32 +867,12 @@ EnterCarriageReturn:
// 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 &&
+ if (Question->OpCode->OpCode == 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);
- }
+ AdjustQuestionValue (QuestionValue, (UINT8)MenuOption->Sequence);
}
- return Status;
+ return ValidateQuestion (Question);
break;
case CHAR_BACKSPACE:
@@ -822,10 +884,10 @@ EnterCarriageReturn:
// Remove a character
//
EditValue = PreviousNumber[Count - 1];
- UpdateStatusBar (Selection, INPUT_ERROR, Question->QuestionFlags, FALSE);
+ UpdateStatusBar (INPUT_ERROR, FALSE);
Count--;
Column--;
- PrintAt (Column, Row, L" ");
+ PrintStringAt (Column, Row, L" ");
}
break;
@@ -839,12 +901,12 @@ EnterCarriageReturn:
} 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);
+ UpdateStatusBar (INPUT_ERROR, TRUE);
break;
}
} else {
if (Key.UnicodeChar > L'9' || Key.UnicodeChar < L'0') {
- UpdateStatusBar (Selection, INPUT_ERROR, Question->QuestionFlags, TRUE);
+ UpdateStatusBar (INPUT_ERROR, TRUE);
break;
}
}
@@ -873,32 +935,178 @@ EnterCarriageReturn:
}
if (EditValue > Maximum) {
- UpdateStatusBar (Selection, INPUT_ERROR, Question->QuestionFlags, TRUE);
+ UpdateStatusBar (INPUT_ERROR, TRUE);
ASSERT (Count < sizeof (PreviousNumber) / sizeof (PreviousNumber[0]));
EditValue = PreviousNumber[Count];
break;
} else {
- UpdateStatusBar (Selection, INPUT_ERROR, Question->QuestionFlags, FALSE);
+ 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 Selection Pointer to current selection.
@param MenuOption Pointer to the current input menu.
@retval EFI_SUCCESS If Option input is processed successfully
@@ -907,7 +1115,6 @@ EnterCarriageReturn:
**/
EFI_STATUS
GetSelectionInputPopUp (
- IN UI_MENU_SELECTION *Selection,
IN UI_MENU_OPTION *MenuOption
)
{
@@ -934,16 +1141,16 @@ GetSelectionInputPopUp (
LIST_ENTRY *Link;
BOOLEAN OrderedList;
UINT8 *ValueArray;
+ UINT8 *ReturnValue;
UINT8 ValueType;
EFI_HII_VALUE HiiValue;
- EFI_HII_VALUE *HiiValueArray;
- UINTN OptionCount;
- QUESTION_OPTION *OneOfOption;
- QUESTION_OPTION *CurrentOption;
- FORM_BROWSER_STATEMENT *Question;
+ DISPLAY_QUESTION_OPTION *OneOfOption;
+ DISPLAY_QUESTION_OPTION *CurrentOption;
+ FORM_DISPLAY_ENGINE_STATEMENT *Question;
INTN Result;
+ EFI_IFR_ORDERED_LIST *OrderList;
- DimensionsWidth = gScreenDimensions.RightColumn - gScreenDimensions.LeftColumn;
+ DimensionsWidth = gStatementDimensions.RightColumn - gStatementDimensions.LeftColumn;
ValueArray = NULL;
ValueType = 0;
@@ -954,80 +1161,33 @@ GetSelectionInputPopUp (
StringPtr = AllocateZeroPool ((gOptionBlockWidth + 1) * 2);
ASSERT (StringPtr);
+ ZeroMem (&HiiValue, sizeof (EFI_HII_VALUE));
+
Question = MenuOption->ThisTag;
- if (Question->Operand == EFI_IFR_ORDERED_LIST_OP) {
- ValueArray = Question->BufferValue;
- ValueType = Question->ValueType;
+ 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) {
- for (Index = 0; Index < Question->MaxContainers; Index++) {
- if (GetArrayData (ValueArray, ValueType, Index) == 0) {
- break;
- }
- }
-
- OptionCount = Index;
+ AdjustOptionOrder(Question, &PopUpMenuLines);
} else {
- OptionCount = 0;
Link = GetFirstNode (&Question->OptionListHead);
while (!IsNull (&Question->OptionListHead, Link)) {
- OneOfOption = QUESTION_OPTION_FROM_LINK (Link);
-
- OptionCount++;
-
- Link = GetNextNode (&Question->OptionListHead, Link);
- }
- }
-
- //
- // Prepare HiiValue array
- //
- HiiValueArray = AllocateZeroPool (OptionCount * sizeof (EFI_HII_VALUE));
- ASSERT (HiiValueArray != NULL);
- Link = GetFirstNode (&Question->OptionListHead);
- for (Index = 0; Index < OptionCount; Index++) {
- if (OrderedList) {
- HiiValueArray[Index].Type = ValueType;
- HiiValueArray[Index].Value.u64 = GetArrayData (ValueArray, ValueType, Index);
- } else {
- OneOfOption = QUESTION_OPTION_FROM_LINK (Link);
- CopyMem (&HiiValueArray[Index], &OneOfOption->Value, sizeof (EFI_HII_VALUE));
- Link = GetNextNode (&Question->OptionListHead, Link);
- }
- }
-
- //
- // Move Suppressed Option to list tail
- //
- PopUpMenuLines = 0;
- for (Index = 0; Index < OptionCount; Index++) {
- OneOfOption = ValueToOption (Question, &HiiValueArray[OptionCount - Index - 1]);
- if (OneOfOption == NULL) {
- return EFI_NOT_FOUND;
- }
-
- RemoveEntryList (&OneOfOption->Link);
-
- if ((OneOfOption->SuppressExpression != NULL) &&
- EvaluateExpressionList(OneOfOption->SuppressExpression, FALSE, NULL, NULL) != ExpressFalse) {
- //
- // This option is suppressed, insert to tail
- //
- InsertTailList (&Question->OptionListHead, &OneOfOption->Link);
- } else {
- //
- // Insert to head
- //
- InsertHeadList (&Question->OptionListHead, &OneOfOption->Link);
-
+ OneOfOption = DISPLAY_QUESTION_OPTION_FROM_LINK (Link);
PopUpMenuLines++;
+ Link = GetNextNode (&Question->OptionListHead, Link);
}
}
@@ -1038,15 +1198,16 @@ GetSelectionInputPopUp (
HighlightOptionIndex = 0;
Link = GetFirstNode (&Question->OptionListHead);
for (Index = 0; Index < PopUpMenuLines; Index++) {
- OneOfOption = QUESTION_OPTION_FROM_LINK (Link);
+ OneOfOption = DISPLAY_QUESTION_OPTION_FROM_LINK (Link);
- StringPtr = GetToken (OneOfOption->Text, MenuOption->Handle);
+ StringPtr = GetToken (OneOfOption->OptionOpCode->Option, gFormData->HiiHandle);
if (StrLen (StringPtr) > PopUpWidth) {
PopUpWidth = StrLen (StringPtr);
}
FreePool (StringPtr);
-
- if (!OrderedList && (CompareHiiValue (&Question->HiiValue, &OneOfOption->Value, &Result, NULL) == EFI_SUCCESS) && (Result == 0)) {
+ 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
//
@@ -1062,16 +1223,16 @@ GetSelectionInputPopUp (
PopUpWidth = PopUpWidth + POPUP_PAD_SPACE_COUNT;
SavedAttribute = gST->ConOut->Mode->Attribute;
- gST->ConOut->SetAttribute (gST->ConOut, POPUP_TEXT | POPUP_BACKGROUND);
+ gST->ConOut->SetAttribute (gST->ConOut, GetPopupColor ());
if ((PopUpWidth + POPUP_FRAME_WIDTH) > DimensionsWidth) {
PopUpWidth = DimensionsWidth - POPUP_FRAME_WIDTH;
}
- Start = (DimensionsWidth - PopUpWidth - POPUP_FRAME_WIDTH) / 2 + gScreenDimensions.LeftColumn;
+ Start = (DimensionsWidth - PopUpWidth - POPUP_FRAME_WIDTH) / 2 + gStatementDimensions.LeftColumn;
End = Start + PopUpWidth + POPUP_FRAME_WIDTH;
- Top = gScreenDimensions.TopRow + NONE_FRONT_PAGE_HEADER_HEIGHT;
- Bottom = gScreenDimensions.BottomRow - STATUS_BAR_HEIGHT - gFooterHeight - 1;
+ Top = gStatementDimensions.TopRow;
+ Bottom = gStatementDimensions.BottomRow - 1;
MenuLinesInView = Bottom - Top - 1;
if (MenuLinesInView >= PopUpMenuLines) {
@@ -1091,7 +1252,7 @@ GetSelectionInputPopUp (
//
// Clear that portion of the screen
//
- ClearLines (Start, End, Top, Bottom, POPUP_TEXT | POPUP_BACKGROUND);
+ ClearLines (Start, End, Top, Bottom, GetPopupColor ());
//
// Draw "One of" pop-up menu
@@ -1105,11 +1266,11 @@ GetSelectionInputPopUp (
Character = BOXDRAW_HORIZONTAL;
}
- PrintChar (Character);
+ PrintCharAt ((UINTN)-1, (UINTN)-1, Character);
}
Character = BOXDRAW_DOWN_LEFT;
- PrintChar (Character);
+ PrintCharAt ((UINTN)-1, (UINTN)-1, Character);
Character = BOXDRAW_VERTICAL;
for (Index = Top + 1; Index < Bottom; Index++) {
PrintCharAt (Start, Index, Character);
@@ -1129,10 +1290,10 @@ GetSelectionInputPopUp (
//
Index2 = Top + 1;
for (Index = TopOptionIndex; (Index < PopUpMenuLines) && (Index2 < Bottom); Index++) {
- OneOfOption = QUESTION_OPTION_FROM_LINK (Link);
+ OneOfOption = DISPLAY_QUESTION_OPTION_FROM_LINK (Link);
Link = GetNextNode (&Question->OptionListHead, Link);
- StringPtr = GetToken (OneOfOption->Text, MenuOption->Handle);
+ StringPtr = GetToken (OneOfOption->OptionOpCode->Option, gFormData->HiiHandle);
ASSERT (StringPtr != NULL);
//
// If the string occupies multiple lines, truncate it to fit in one line,
@@ -1153,11 +1314,11 @@ GetSelectionInputPopUp (
//
CurrentOption = OneOfOption;
- gST->ConOut->SetAttribute (gST->ConOut, PICKLIST_HIGHLIGHT_TEXT | PICKLIST_HIGHLIGHT_BACKGROUND);
+ gST->ConOut->SetAttribute (gST->ConOut, GetPickListColor ());
PrintStringAt (Start + 2, Index2, StringPtr);
- gST->ConOut->SetAttribute (gST->ConOut, POPUP_TEXT | POPUP_BACKGROUND);
+ gST->ConOut->SetAttribute (gST->ConOut, GetPopupColor ());
} else {
- gST->ConOut->SetAttribute (gST->ConOut, POPUP_TEXT | POPUP_BACKGROUND);
+ gST->ConOut->SetAttribute (gST->ConOut, GetPopupColor ());
PrintStringAt (Start + 2, Index2, StringPtr);
}
@@ -1174,11 +1335,11 @@ GetSelectionInputPopUp (
Character = BOXDRAW_HORIZONTAL;
}
- PrintChar (Character);
+ PrintCharAt ((UINTN)-1, (UINTN)-1, Character);
}
Character = BOXDRAW_UP_LEFT;
- PrintChar (Character);
+ PrintCharAt ((UINTN)-1, (UINTN)-1, Character);
//
// Get User selection
@@ -1294,7 +1455,7 @@ TheKey:
if (OrderedList) {
HiiValue.Type = ValueType;
HiiValue.Value.u64 = 0;
- for (Index = 0; Index < Question->MaxContainers; Index++) {
+ for (Index = 0; Index < OrderList->MaxContainers; Index++) {
HiiValue.Value.u64 = GetArrayData (ValueArray, ValueType, Index);
if (HiiValue.Value.u64 == 0) {
break;
@@ -1310,7 +1471,6 @@ TheKey:
}
}
- FreePool (HiiValueArray);
return EFI_DEVICE_ERROR;
default:
@@ -1324,41 +1484,44 @@ TheKey:
// 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 = QUESTION_OPTION_FROM_LINK (Link);
+ OneOfOption = DISPLAY_QUESTION_OPTION_FROM_LINK (Link);
+ Link = GetNextNode (&Question->OptionListHead, Link);
- SetArrayData (ValueArray, ValueType, Index, OneOfOption->Value.Value.u64);
+ SetArrayData (ReturnValue, ValueType, Index, OneOfOption->OptionOpCode->Value.u64);
Index++;
- if (Index > Question->MaxContainers) {
+ if (Index > OrderList->MaxContainers) {
break;
}
-
- Link = GetNextNode (&Question->OptionListHead, Link);
+ }
+ 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);
- CopyMem (&Question->HiiValue, &CurrentOption->Value, sizeof (EFI_HII_VALUE));
+ 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);
- FreePool (HiiValueArray);
-
- 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;
+ return ValidateQuestion (Question);
+
default:
break;
}
@@ -1366,32 +1529,3 @@ TheKey:
}
-/**
- 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/DisplayEngineDxe/ProcessOptions.c b/MdeModulePkg/Universal/DisplayEngineDxe/ProcessOptions.c
new file mode 100644
index 0000000..aca043a
--- /dev/null
+++ b/MdeModulePkg/Universal/DisplayEngineDxe/ProcessOptions.c
@@ -0,0 +1,1286 @@
+/** @file
+Implementation for handling the User Interface option processing.
+
+
+Copyright (c) 2004 - 2012, Intel Corporation. All rights reserved.<BR>
+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/Expression.c b/MdeModulePkg/Universal/SetupBrowserDxe/Expression.c
index a4e0c02..b977fb0 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;
@@ -1446,7 +1446,6 @@ IfrMid (
UINTN Base;
UINTN Length;
CHAR16 *SubString;
- UINT8 *Buffer;
UINT16 BufferLen;
ZeroMem (Value, sizeof (Value));
@@ -1502,7 +1501,6 @@ IfrMid (
FreePool (String);
} else {
- Buffer = Value[2].Buffer;
BufferLen = Value[2].BufferLen;
Result->Type = EFI_IFR_TYPE_BUFFER;
@@ -2107,7 +2105,7 @@ GetQuestionValueFromForm (
//
FormSet = AllocateZeroPool (sizeof (FORM_BROWSER_FORMSET));
ASSERT (FormSet != NULL);
- Status = InitializeFormSet(HiiHandle, FormSetGuid, FormSet, FALSE);
+ Status = InitializeFormSet(HiiHandle, FormSetGuid, FormSet);
if (EFI_ERROR (Status)) {
GetTheVal = FALSE;
goto Done;
@@ -2802,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);
+ Status = SetValueByName (OpCode->VarStorage, OpCode->ValueName, NameValue, GetSetValueWithEditBuffer, NULL);
FreePool (NameValue);
if (!EFI_ERROR (Status)) {
Data1.Value.b = TRUE;
diff --git a/MdeModulePkg/Universal/SetupBrowserDxe/Expression.h b/MdeModulePkg/Universal/SetupBrowserDxe/Expression.h
new file mode 100644
index 0000000..5660a99
--- /dev/null
+++ b/MdeModulePkg/Universal/SetupBrowserDxe/Expression.h
@@ -0,0 +1,265 @@
+/** @file
+Private structure, MACRO and function definitions for User Interface related functionalities.
+
+Copyright (c) 2004 - 2013, Intel Corporation. All rights reserved.<BR>
+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 a75f2da..ce72672 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) {
//
- // We are currently not in a Form Scope, so just skip this Statement
+ // Only guid op may out side the form level.
//
- return NULL;
+ ASSERT (((EFI_IFR_OP_HEADER *) OpCodeData)->OpCode == EFI_IFR_GUID_OP);
}
Statement = &FormSet->StatementBuffer[mStatementIndex];
@@ -58,6 +58,7 @@ 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));
@@ -82,8 +83,11 @@ CreateStatement (
//
// Insert this Statement into current Form
//
- InsertTailList (&Form->StatementListHead, &Statement->Link);
-
+ if (Form == NULL) {
+ InsertTailList (&FormSet->StatementListOSF, &Statement->Link);
+ } else {
+ InsertTailList (&Form->StatementListHead, &Statement->Link);
+ }
return Statement;
}
@@ -1133,6 +1137,7 @@ 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;
@@ -1144,6 +1149,7 @@ ParseOpCodes (
return EFI_OUT_OF_RESOURCES;
}
+ InitializeListHead (&FormSet->StatementListOSF);
InitializeListHead (&FormSet->StorageListHead);
InitializeListHead (&FormSet->DefaultStoreListHead);
InitializeListHead (&FormSet->FormListHead);
@@ -1502,7 +1508,6 @@ 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));
@@ -1539,7 +1544,6 @@ 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);
@@ -1653,7 +1657,7 @@ ParseOpCodes (
ASSERT (CurrentStatement != NULL);
CurrentStatement->Flags = ((EFI_IFR_SUBTITLE *) OpCodeData)->Flags;
-
+ CurrentStatement->FakeQuestionId = mUsedQuestionId++;
if (Scope != 0) {
mInScopeSubtitle = TRUE;
}
@@ -1662,13 +1666,14 @@ 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;
@@ -1887,8 +1892,10 @@ ParseOpCodes (
CurrentDefault->Value.Type = ((EFI_IFR_DEFAULT *) OpCodeData)->Type;
CopyMem (&CurrentDefault->DefaultId, &((EFI_IFR_DEFAULT *) OpCodeData)->DefaultId, sizeof (UINT16));
- CopyMem (&CurrentDefault->Value.Value, &((EFI_IFR_DEFAULT *) OpCodeData)->Value, sizeof (EFI_IFR_TYPE_VALUE));
- ExtendValueToU64 (&CurrentDefault->Value);
+ if (OpCodeLength > OFFSET_OF (EFI_IFR_DEFAULT, Value)) {
+ CopyMem (&CurrentDefault->Value.Value, &((EFI_IFR_DEFAULT *) OpCodeData)->Value, OpCodeLength - OFFSET_OF (EFI_IFR_DEFAULT, Value));
+ ExtendValueToU64 (&CurrentDefault->Value);
+ }
//
// Insert to Default Value list of current Question
@@ -1911,6 +1918,7 @@ 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;
@@ -2268,45 +2276,8 @@ ParseOpCodes (
//
// Vendor specific
//
- 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;
- }
- }
-
+ case EFI_IFR_GUID_OP:
+ CurrentStatement = CreateStatement (OpCodeData, FormSet, CurrentForm);
break;
//
diff --git a/MdeModulePkg/Universal/SetupBrowserDxe/Presentation.c b/MdeModulePkg/Universal/SetupBrowserDxe/Presentation.c
index c3854aa..def18fd 100644
--- a/MdeModulePkg/Universal/SetupBrowserDxe/Presentation.c
+++ b/MdeModulePkg/Universal/SetupBrowserDxe/Presentation.c
@@ -19,863 +19,1658 @@ 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;
/**
- Clear retangle with specified text attribute.
+ 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 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.
+ @param Event The Event need to be process
+ @param Context The context of the event.
**/
VOID
-ClearLines (
- IN UINTN LeftColumn,
- IN UINTN RightColumn,
- IN UINTN TopRow,
- IN UINTN BottomRow,
- IN UINTN TextAttribute
+EFIAPI
+SetupBrowserEmptyFunction (
+ IN EFI_EVENT Event,
+ IN VOID *Context
)
{
- CHAR16 *Buffer;
- UINTN Row;
+}
- //
- // For now, allocate an arbitrarily long buffer
- //
- Buffer = AllocateZeroPool (0x10000);
- ASSERT (Buffer != NULL);
+/**
+ Base on the opcode buffer info to get the display statement.
- //
- // Set foreground and background as defined
- //
- gST->ConOut->SetAttribute (gST->ConOut, TextAttribute);
+ @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);
//
- // Much faster to buffer the long string instead of print it a character at a time
+ // Reset FormPackage update flag
//
- SetUnicodeMem (Buffer, RightColumn - LeftColumn, L' ');
+ mHiiPackageListUpdated = FALSE;
//
- // Clear the desired area with the appropriate foreground/background
+ // Question value may be changed, need invoke its Callback()
//
- for (Row = TopRow; Row <= BottomRow; Row++) {
- PrintStringAt (LeftColumn, Row, Buffer);
+ 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;
}
+}
- gST->ConOut->SetCursorPosition (gST->ConOut, LeftColumn, TopRow);
+/**
+ 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;
- FreePool (Buffer);
- return ;
+ Statement = (FORM_BROWSER_STATEMENT *)Context;
+ UpdateStatement(Statement);
+ gBS->SignalEvent (mValueChangedEvent);
}
+
/**
- Concatenate a narrow string to another string.
+ Create refresh hook event for statement which has refresh event or interval.
- @param Destination The destination string.
- @param Source The source string. The string to be concatenated.
- to the end of Destination.
+ @param Statement The statement need to check.
**/
VOID
-NewStrCat (
- IN OUT CHAR16 *Destination,
- IN CHAR16 *Source
+CreateRefreshEvent (
+ IN FORM_BROWSER_STATEMENT *Statement
)
{
- UINTN Length;
-
- for (Length = 0; Destination[Length] != 0; Length++)
- ;
+ EFI_STATUS Status;
+ EFI_EVENT RefreshEvent;
+ FORM_BROWSER_REFRESH_EVENT_NODE *EventNode;
//
- // 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
+ // If question has refresh guid, create the notify function.
//
- Destination[Length] = NARROW_CHAR;
- Length++;
-
- StrCpy (Destination + Length, Source);
+ 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);
}
/**
- Count the storage space of a Unicode string.
+ 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;
- 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.
+ RetVal = STATEMENT_VALID;
+ ListHead = &Question->InconsistentListHead;
- If String is NULL, then ASSERT ().
+ Link = GetFirstNode (ListHead);
+ while (!IsNull (ListHead, Link)) {
+ Expression = FORM_EXPRESSION_FROM_LINK (Link);
+ Link = GetNextNode (ListHead, Link);
- @param String The input string to be counted.
+ //
+ // 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 Storage space for the input string.
+ 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.
**/
-UINTN
-GetStringWidth (
- IN CHAR16 *String
+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
)
{
- UINTN Index;
- UINTN Count;
- UINTN IncrementValue;
+ 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;
- ASSERT (String != NULL);
- if (String == NULL) {
- return 0;
+ default:
+ CopyMem (&BackUpValue, &Question->HiiValue, sizeof (EFI_HII_VALUE));
+ CopyMem (&Question->HiiValue, InputValue, sizeof (EFI_HII_VALUE));
+ break;
}
- Index = 0;
- Count = 0;
- IncrementValue = 1;
+ //
+ // Do the inconsistentif check.
+ //
+ if (!IsListEmpty (&Question->InconsistentListHead)) {
+ RetVal = InConsistentIfCheck(Question, ErrorInfo);
+ }
- 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
- )
- ;
+ //
+ // Restore the quesion value.
+ //
+ switch (Question->Operand) {
+ case EFI_IFR_ORDERED_LIST_OP:
+ CopyMem (Question->BufferValue, BackUpBuffer, Question->StorageWidth);
+ break;
- //
- // We hit the null-terminator, we now have a count
- //
- if (String[Index] == 0) {
- 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) {
//
- // 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)
+ // Ordered list opcode may not initilized, get default value here.
//
- if (String[Index] == NARROW_CHAR) {
- //
- // Skip to the next character
- //
- Index++;
- IncrementValue = 1;
- } else {
- //
- // Skip to the next character
- //
- Index++;
- IncrementValue = 2;
+ if (Statement->OpCode->OpCode == EFI_IFR_ORDERED_LIST_OP && GetArrayData (Statement->BufferValue, Statement->ValueType, 0) == 0) {
+ GetQuestionDefault (gCurrentSelection->FormSet, gCurrentSelection->Form, Statement, 0);
}
- } while (String[Index] != 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;
+ }
//
- // Increment by one to include the null-terminator in the size
+ // Save the password check function for later use.
//
- Count++;
+ 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;
+ }
- return Count * sizeof (CHAR16);
+ //
+ // 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);
+ }
}
/**
- This function displays the page frame.
+ Process for the refresh interval statement.
+
+ @param Event The Event need to be process
+ @param Context The context of the event.
- @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
+EFIAPI
+RefreshIntervalProcess (
+ IN EFI_EVENT Event,
+ IN VOID *Context
)
{
- 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;
+ 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.
- CopyMem (&LocalScreen, &gScreenDimensions, sizeof (EFI_SCREEN_DESCRIPTOR));
+**/
+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;
//
- // For now, allocate an arbitrarily long buffer
+ // Process the statement outside the form, these statements are not recognized
+ // by browser core.
//
- Buffer = AllocateZeroPool (0x10000);
- ASSERT (Buffer != NULL);
+ 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;
- Character = BOXDRAW_HORIZONTAL;
+ InitializeListHead (&DisplayStatement->NestStatementList);
+ InitializeListHead (&DisplayStatement->OptionListHead);
- for (Index = 0; Index + 2 < (LocalScreen.RightColumn - LocalScreen.LeftColumn); Index++) {
- Buffer[Index] = Character;
+ InsertTailList(&gDisplayFormData.StatementListOSF, &DisplayStatement->DisplayLink);
}
- if ((gClassOfVfr & FORMSET_CLASS_FRONT_PAGE) == FORMSET_CLASS_FRONT_PAGE) {
+ //
+ // 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);
+
//
- // ClearLines(0, LocalScreen.RightColumn, 0, BANNER_HEIGHT-1, BANNER_TEXT | BANNER_BACKGROUND);
+ // This statement can't be show, skip it.
//
- ClearLines (
- LocalScreen.LeftColumn,
- LocalScreen.RightColumn,
- LocalScreen.TopRow,
- FRONT_PAGE_HEADER_HEIGHT - 1 + LocalScreen.TopRow,
- BANNER_TEXT | BANNER_BACKGROUND
- );
+ if (EvaluateExpressionList(Statement->Expression, FALSE, NULL, NULL) > ExpressGrayOut) {
+ continue;
+ }
+
+ DisplayStatement = AllocateZeroPool (sizeof (FORM_DISPLAY_ENGINE_STATEMENT));
+ ASSERT (DisplayStatement != NULL);
+
//
- // for (Line = 0; Line < BANNER_HEIGHT; Line++) {
+ // Initialize this statement and add it to the display form.
//
- for (Line = (UINT8) LocalScreen.TopRow; Line < BANNER_HEIGHT + (UINT8) LocalScreen.TopRow; Line++) {
- //
- // for (Alignment = 0; Alignment < BANNER_COLUMNS; Alignment++) {
- //
- 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;
- }
+ InitializeDisplayStatement(DisplayStatement, Statement, HostDisplayStatement);
- 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;
+ //
+ // Save the Host statement info.
+ // Host statement may has nest statement follow it.
+ //
+ if (!Statement->InSubtitle) {
+ HostDisplayStatement = DisplayStatement;
+ }
- case 2:
- //
- // Handle right column
- //
- PrintStringAt (
- LocalScreen.LeftColumn + (LocalScreen.RightColumn - LocalScreen.LeftColumn) * 2 / 3,
- Line,
- StrFrontPageBanner
- );
- break;
- }
+ if (Statement->Storage != NULL) {
+ FormEditable = TRUE;
+ }
- FreePool (StrFrontPageBanner);
- }
+ //
+ // Get the minimal refresh interval value for later use.
+ //
+ if ((Statement->RefreshInterval != 0) &&
+ (MinRefreshInterval == 0 || Statement->RefreshInterval < MinRefreshInterval)) {
+ MinRefreshInterval = Statement->RefreshInterval;
}
}
- 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);
- }
+ //
+ // 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);
+ }
- Character = BOXDRAW_UP_RIGHT;
- PrintCharAt (LocalScreen.LeftColumn, LocalScreen.TopRow + NONE_FRONT_PAGE_HEADER_HEIGHT - 1, Character);
- PrintString (Buffer);
+ //
+ // Update hotkey list field.
+ //
+ if (gBrowserSettingScope == SystemLevel || FormEditable) {
+ UpdateHotkeyList();
+ }
+}
- Character = BOXDRAW_UP_LEFT;
- PrintChar (Character);
+/**
- if ((gClassOfVfr & FORMSET_CLASS_PLATFORM_SETUP) == FORMSET_CLASS_PLATFORM_SETUP) {
- //
- // Print Bottom border line
- // +------------------------------------------------------------------------------+
- // ? ?
- // +------------------------------------------------------------------------------+
- //
- 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);
- }
+ Initialize the SettingChangedFlag variable in the display form.
- Character = BOXDRAW_UP_RIGHT;
- PrintCharAt (LocalScreen.LeftColumn, LocalScreen.BottomRow - STATUS_BAR_HEIGHT - 1, Character);
+**/
+VOID
+UpdateDataChangedFlag (
+ VOID
+ )
+{
+ LIST_ENTRY *Link;
+ FORM_BROWSER_FORMSET *LocalFormSet;
- PrintString (Buffer);
+ gDisplayFormData.SettingChangedFlag = FALSE;
- Character = BOXDRAW_UP_LEFT;
- PrintChar (Character);
- }
+ if (IsNvUpdateRequiredForForm (gCurrentSelection->Form)) {
+ gDisplayFormData.SettingChangedFlag = TRUE;
+ return;
}
- FreePool (Buffer);
+ //
+ // 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;
+ }
}
-
/**
- Evaluate all expressions in a Form.
- @param FormSet FormSet this Form belongs to.
- @param Form The Form.
+ Initialize the Display form structure data.
- @retval EFI_SUCCESS The expression evaluated successfuly
+**/
+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.
**/
-EFI_STATUS
-EvaluateFormExpressions (
- IN FORM_BROWSER_FORMSET *FormSet,
- IN FORM_BROWSER_FORM *Form
+VOID
+FreeHotkeyList (
+ VOID
)
{
- EFI_STATUS Status;
+ BROWSER_HOT_KEY *HotKey;
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);
+ while (!IsListEmpty (&gDisplayFormData.HotKeyListHead)) {
+ Link = GetFirstNode (&gDisplayFormData.HotKeyListHead);
+ HotKey = BROWSER_HOT_KEY_FROM_LINK (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;
- }
+ RemoveEntryList (&HotKey->Link);
- Status = EvaluateExpression (FormSet, Form, Expression);
- if (EFI_ERROR (Status)) {
- return Status;
- }
+ FreePool (HotKey->KeyData);
+ FreePool (HotKey->HelpString);
+ FreePool (HotKey);
}
+}
- return EFI_SUCCESS;
+/**
+
+ 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 ();
}
-/*
-+------------------------------------------------------------------------------+
-? Setup Page ?
-+------------------------------------------------------------------------------+
+/**
+
+ 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);
+ }
+ //
+ // Free nest statement List
+ //
+ if (!IsListEmpty (&Statement->NestStatementList)) {
+ FreeStatementData(&Statement->NestStatementList);
+ }
+ RemoveEntryList (&Statement->DisplayLink);
+ FreePool (Statement);
+ }
+}
+/**
+ Free the Display form structure data.
+**/
+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;
+ }
-+------------------------------------------------------------------------------+
-?F1=Scroll Help F9=Reset to Defaults F10=Save and Exit ?
-| ^"=Move Highlight <Spacebar> Toggles Checkbox Esc=Discard Changes |
-+------------------------------------------------------------------------------+
-*/
+ Link = GetNextNode (&gCurrentSelection->Form->StatementListHead, Link);
+ }
+
+ return NULL;
+}
/**
+ Process the action request in user input.
- Display form and wait for user to select one menu option, then return it.
+ @param Action The user input action request info.
+ @param DefaultId The user input default Id info.
- @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
-DisplayForm (
- IN OUT UI_MENU_SELECTION *Selection
+EFI_STATUS
+ProcessAction (
+ IN UINT32 Action,
+ IN UINT16 DefaultId
)
{
- 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;
+ 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;
+ }
- Handle = Selection->Handle;
- MenuItemCount = 0;
- ArrayEntry = 0;
- OutputString = NULL;
+ //
+ // 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);
+ }
- UiInitMenu ();
+ if ((Action & BROWSER_ACTION_DEFAULT) == BROWSER_ACTION_DEFAULT) {
+ ExtractDefault (gCurrentSelection->FormSet, gCurrentSelection->Form, DefaultId, gBrowserSettingScope, GetDefaultForAll, NULL, FALSE);
+ }
- CopyMem (&LocalScreen, &gScreenDimensions, sizeof (EFI_SCREEN_DESCRIPTOR));
+ if ((Action & BROWSER_ACTION_SUBMIT) == BROWSER_ACTION_SUBMIT) {
+ Status = SubmitForm (gCurrentSelection->FormSet, gCurrentSelection->Form, gBrowserSettingScope);
+ if (EFI_ERROR (Status)) {
+ gBrowserStatus = BROWSER_SUBMIT_FAIL;
+ }
+ }
- StringPtr = GetToken (Selection->Form->FormTitle, Handle);
+ if ((Action & BROWSER_ACTION_RESET) == BROWSER_ACTION_RESET) {
+ gResetRequired = TRUE;
+ }
- 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);
+ 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;
}
- PrintStringAt (
- (LocalScreen.RightColumn + LocalScreen.LeftColumn - GetStringWidth (StringPtr) / 2) / 2,
- LocalScreen.TopRow + 1,
- StringPtr
- );
}
+ 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
+ )
+{
+ 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;
//
- // Remove Buffer allocated for StringPtr after it has been used.
+ // Locate Device Path Protocol handle buffer
//
- FreePool (StringPtr);
+ Status = gBS->LocateDevicePath (
+ &gEfiDevicePathProtocolGuid,
+ &TmpDevicePath,
+ &DriverHandle
+ );
+ if (EFI_ERROR (Status) || !IsDevicePathEnd (TmpDevicePath)) {
+ return NULL;
+ }
//
- // Evaluate all the Expressions in this Form
+ // Retrieve all HII Handles from HII database
//
- Status = EvaluateFormExpressions (Selection->FormSet, Selection->Form);
+ 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)) {
- return Status;
+ FreePool (HiiHandles);
+ return NULL;
}
- Selection->FormEditable = FALSE;
- Link = GetFirstNode (&Selection->Form->StatementListHead);
- while (!IsNull (&Selection->Form->StatementListHead, Link)) {
- Statement = FORM_BROWSER_STATEMENT_FROM_LINK (Link);
+ //
+ // 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;
+ }
+ }
- if (EvaluateExpressionList(Statement->Expression, FALSE, NULL, NULL) <= ExpressGrayOut) {
- StringPtr = GetToken (Statement->Prompt, Handle);
- ASSERT (StringPtr != NULL);
+ FreePool (HiiHandles);
+ return HiiHandle;
+}
- Width = GetWidth (Statement, Handle);
+/**
+ Find HII Handle in the HII database associated with given form set guid.
- 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++;
- }
+ If FormSetGuid is NULL, then ASSERT.
- FreePool (OutputString);
- }
+ @param ComparingGuid FormSet Guid associated with the HII package list
+ handle.
- //
- // We are NOT!! removing this StringPtr buffer via FreePool since it is being used in the menuoptions, we will do
- // it in UiFreeMenu.
- //
- MenuOption = UiAddMenuOption (StringPtr, Selection->Handle, Selection->Form, Statement, NumberOfLines, MenuItemCount);
- MenuItemCount++;
+ @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));
- if (MenuOption->IsQuestion && !MenuOption->ReadOnly) {
+ while (Offset < PackageListLength) {
+ Package = ((UINT8 *) HiiPackageList) + Offset;
+ CopyMem (&PackageHeader, Package, sizeof (EFI_HII_PACKAGE_HEADER));
+
+ if (PackageHeader.Type == EFI_HII_PACKAGE_FORMS) {
//
- // At least one item is not readonly, this Form is considered as editable
+ // Search FormSet in this Form Package
//
- Selection->FormEditable = TRUE;
+ 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;
}
-
- Link = GetNextNode (&Selection->Form->StatementListHead, Link);
+
+ FreePool (HiiPackageList);
+ if (HiiHandle != NULL) {
+ break;
+ }
}
- Status = UiDisplayMenu (Selection);
-
- UiFreeMenu ();
+ FreePool (HiiHandles);
- return Status;
+ return HiiHandle;
}
/**
- Initialize the HII String Token to the correct values.
+ 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.
+
+ @param Scope Data save or discard scope, form or formset.
+
+ @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.
**/
-VOID
-InitializeBrowserStrings (
- VOID
+BOOLEAN
+ProcessChangedData (
+ IN OUT UI_MENU_SELECTION *Selection,
+ IN BROWSER_SETTING_SCOPE Scope
)
{
- 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 ;
+ 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;
+
+ case BROWSER_ACTION_NONE:
+ RetValue = FALSE;
+ break;
+
+ default:
+ //
+ // if Invalid value return, process same as BROWSER_ACTION_NONE.
+ //
+ RetValue = FALSE;
+ break;
+ }
+
+ return RetValue;
}
/**
- Free up the resource allocated for all strings required
- by Setup Browser.
+ Find parent formset menu(the first menu which has different formset) for current menu.
+ If not find, just return to the first menu.
+
+ @param Selection The selection info.
**/
VOID
-FreeBrowserStrings (
- VOID
+FindParentFormSet (
+ IN OUT UI_MENU_SELECTION *Selection
)
{
- 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 ;
+ FORM_ENTRY_INFO *CurrentMenu;
+ FORM_ENTRY_INFO *ParentMenu;
+
+ CurrentMenu = Selection->CurrentMenu;
+ ParentMenu = UiFindParentMenu(CurrentMenu);
+
+ //
+ // Find a menu which has different formset guid with current.
+ //
+ 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;
+ }
+
+ Selection->Statement = NULL;
}
/**
- Show all registered HotKey help strings on bottom Rows.
+ 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.
+
+ @retval EFI_SUCCESS The menu process successfully.
+ @return Other value if the process failed.
**/
-VOID
-PrintHotKeyHelpString (
- VOID
+EFI_STATUS
+ProcessGotoOpCode (
+ IN OUT FORM_BROWSER_STATEMENT *Statement,
+ IN OUT UI_MENU_SELECTION *Selection
)
{
- UINTN CurrentCol;
- UINTN CurrentRow;
- UINTN BottomRowOfHotKeyHelp;
- UINTN ColumnWidth;
- UINTN Index;
- EFI_SCREEN_DESCRIPTOR LocalScreen;
- LIST_ENTRY *Link;
- BROWSER_HOT_KEY *HotKey;
+ 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;
- CopyMem (&LocalScreen, &gScreenDimensions, sizeof (EFI_SCREEN_DESCRIPTOR));
- ColumnWidth = (LocalScreen.RightColumn - LocalScreen.LeftColumn) / 3;
- BottomRowOfHotKeyHelp = LocalScreen.BottomRow - STATUS_BAR_HEIGHT - 3;
+ //
+ // 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);
+ }
//
- // Calculate total number of Register HotKeys.
+ // Check whether the device path string is a valid string.
//
- Index = 0;
- Link = GetFirstNode (&gBrowserHotKeyList);
- while (!IsNull (&gBrowserHotKeyList, 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';
+ if (Statement->HiiValue.Value.ref.DevicePath != 0 && StringPtr != NULL) {
+ if (Selection->Form->ModalForm) {
+ return Status;
}
+
//
- // Calculate help information Column and Row.
+ // Goto another Hii Package list
//
- if ((Index % 3) != 2) {
- CurrentCol = LocalScreen.LeftColumn + (2 - Index % 3) * ColumnWidth;
+ if (mPathFromText != NULL) {
+ DevicePath = mPathFromText->ConvertTextToDevicePath(StringPtr);
+ if (DevicePath != NULL) {
+ HiiHandle = DevicePathToHiiHandle (DevicePath);
+ FreePool (DevicePath);
+ }
+ FreePool (StringPtr);
} else {
- CurrentCol = LocalScreen.LeftColumn + 2;
+ //
+ // Not found the EFI_DEVICE_PATH_FROM_TEXT_PROTOCOL protocol.
+ //
+ gBrowserStatus = BROWSER_PROTOCOL_NOT_FOUND;
+ FreePool (StringPtr);
+ return Status;
+ }
+
+ 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;
+ }
+ }
+ }
+
+ 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;
+ }
+
+ 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)) {
+ //
+ // Goto another Formset, check for uncommitted data
+ //
+ if ((gBrowserSettingScope == FormLevel || gBrowserSettingScope == FormSetLevel) &&
+ IsNvUpdateRequiredForFormSet(Selection->FormSet)) {
+ if (!ProcessChangedData(Selection, FormSetLevel)) {
+ return EFI_SUCCESS;
+ }
+ }
+ }
+
+ 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;
}
- CurrentRow = BottomRowOfHotKeyHelp - Index / 3;
- //
- // Print HotKey help string on bottom Row.
- //
- PrintStringAt (CurrentCol, CurrentRow, HotKey->HelpString);
+ 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) {
//
- // Get Next Hot Key.
+ // Goto another Form, check for uncommitted data
//
- Link = GetNextNode (&gBrowserHotKeyList, Link);
- Index ++;
+ if (Statement->HiiValue.Value.ref.FormId != Selection->FormId) {
+ if ((gBrowserSettingScope == FormLevel && IsNvUpdateRequiredForForm(Selection->Form))) {
+ if (!ProcessChangedData (Selection, FormLevel)) {
+ return EFI_SUCCESS;
+ }
+ }
+ }
+
+ 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;
+ }
+ }
+
+ 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;
+
+ return Status;
}
+
/**
- Update key's help imformation.
+ Process Question Config.
+
+ @param Selection The UI menu selection.
+ @param Question The Question to be peocessed.
- @param Selection Tell setup browser the information about the Selection
- @param MenuOption The Menu option
- @param Selected Whether or not a tag be selected
+ @retval EFI_SUCCESS Question Config process success.
+ @retval Other Question Config process fail.
**/
-VOID
-UpdateKeyHelp (
- IN UI_MENU_SELECTION *Selection,
- IN UI_MENU_OPTION *MenuOption,
- IN BOOLEAN Selected
+EFI_STATUS
+ProcessQuestionConfig (
+ IN UI_MENU_SELECTION *Selection,
+ IN FORM_BROWSER_STATEMENT *Question
)
{
- UINTN SecCol;
- UINTN ThdCol;
- UINTN LeftColumnOfHelp;
- UINTN RightColumnOfHelp;
- UINTN TopRowOfHelp;
- UINTN BottomRowOfHelp;
- UINTN StartColumnOfHelp;
- EFI_SCREEN_DESCRIPTOR LocalScreen;
- FORM_BROWSER_STATEMENT *Statement;
+ EFI_STATUS Status;
+ CHAR16 *ConfigResp;
+ CHAR16 *Progress;
+ EFI_HII_CONFIG_ACCESS_PROTOCOL *ConfigAccess;
- gST->ConOut->SetAttribute (gST->ConOut, KEYHELP_TEXT | KEYHELP_BACKGROUND);
+ if (Question->QuestionConfig == 0) {
+ return EFI_SUCCESS;
+ }
- if (Selection->Form->ModalForm) {
- return;
+ //
+ // Get <ConfigResp>
+ //
+ 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
+ );
- CopyMem (&LocalScreen, &gScreenDimensions, sizeof (EFI_SCREEN_DESCRIPTOR));
+ return Status;
+}
- SecCol = LocalScreen.LeftColumn + (LocalScreen.RightColumn - LocalScreen.LeftColumn) / 3;
- ThdCol = LocalScreen.LeftColumn + (LocalScreen.RightColumn - LocalScreen.LeftColumn) / 3 * 2;
+/**
- 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;
+ Process the user input data.
- 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);
+ @param UserInput The user input data.
+ @param ChangeHighlight Whether need to change the highlight statement.
+
+ @retval EFI_SUCESSS This function always return successfully for now.
+
+**/
+EFI_STATUS
+ProcessUserInput (
+ IN USER_INPUT *UserInput,
+ IN BOOLEAN ChangeHighlight
+ )
+{
+ EFI_STATUS Status;
+ FORM_BROWSER_STATEMENT *Statement;
+
+ Status = EFI_SUCCESS;
- if (!Selected) {
+ //
+ // When Exit from FormDisplay function, one of the below two cases must be true.
+ //
+ ASSERT (UserInput->Action != 0 || UserInput->SelectedStatement != NULL);
+
+ //
+ // Remove the last highligh question id, this id will update when show next form.
+ //
+ gCurrentSelection->QuestionId = 0;
+
+ //
+ // First process the Action field in USER_INPUT.
+ //
+ if (UserInput->Action != 0) {
+ Status = ProcessAction (UserInput->Action, UserInput->DefaultId);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ //
+ // Clear the highlight info.
+ //
+ gCurrentSelection->Statement = NULL;
+
+ 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.
//
- // On system setting, HotKey will show on every form.
+ gCurrentSelection->CurrentMenu->QuestionId = Statement->QuestionId;
//
- if (gBrowserSettingScope == SystemLevel ||
- (Selection->FormEditable && gFunctionKeySetting != NONE_FUNCTION_KEY_SETTING)) {
- PrintHotKeyHelpString ();
+ // 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 ((gClassOfVfr & FORMSET_CLASS_PLATFORM_SETUP) == FORMSET_CLASS_PLATFORM_SETUP) {
- PrintStringAt (ThdCol, BottomRowOfHelp, gEscapeString);
- }
+ gCurrentSelection->Statement = Statement;
- 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);
+ 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 {
- 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);
+ mCurFakeQestId = 0;
}
- } else {
- PrintStringAt (SecCol, BottomRowOfHelp, gEnterCommitString);
+ }
+ switch (Statement->Operand) {
+ case EFI_IFR_REF_OP:
+ Status = ProcessGotoOpCode(Statement, gCurrentSelection);
+ break;
+
+ case EFI_IFR_ACTION_OP:
//
- // If it is a selected numeric with manual input, display different message
+ // Process the Config string <ConfigResp>
//
- 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);
- }
+ Status = ProcessQuestionConfig (gCurrentSelection, Statement);
+ break;
+
+ case EFI_IFR_RESET_BUTTON_OP:
+ //
+ // Reset Question to default value specified by DefaultId
+ //
+ Status = ExtractDefault (gCurrentSelection->FormSet, NULL, Statement->DefaultId, FormSetLevel, GetDefaultForAll, NULL, FALSE);
+ break;
- if (Statement->Operand == EFI_IFR_ORDERED_LIST_OP) {
- PrintStringAt (StartColumnOfHelp, TopRowOfHelp, gPlusString);
- PrintStringAt (ThdCol, TopRowOfHelp, gMinusString);
- }
+ 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;
- PrintStringAt (ThdCol, BottomRowOfHelp, gEnterEscapeString);
+ case EFI_IFR_PASSWORD_OP:
+ if (UserInput->InputValue.Buffer == NULL) {
+ //
+ // User not input new password, just return.
+ //
+ break;
+ }
+
+ 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);
+ //
+ // Two password match, send it to Configuration Driver
+ //
+ 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);
+ }
+ break;
}
- break;
+ }
+
+ return Status;
+}
+
+/**
+
+ Display form and wait for user to select one menu option, then return it.
+
+ @retval EFI_SUCESSS This function always return successfully for now.
+
+**/
+EFI_STATUS
+DisplayForm (
+ VOID
+ )
+{
+ EFI_STATUS Status;
+ USER_INPUT UserInput;
+ FORM_ENTRY_INFO *CurrentMenu;
+ BOOLEAN ChangeHighlight;
- case EFI_IFR_CHECKBOX_OP:
- ClearLines (LeftColumnOfHelp, RightColumnOfHelp, TopRowOfHelp, BottomRowOfHelp, KEYHELP_TEXT | KEYHELP_BACKGROUND);
+ ZeroMem (&UserInput, sizeof (USER_INPUT));
+ //
+ // Update the menu history data.
+ //
+ CurrentMenu = UiFindMenuList (gCurrentSelection->Handle, &gCurrentSelection->FormSetGuid, gCurrentSelection->FormId);
+ if (CurrentMenu == NULL) {
//
- // On system setting, HotKey will show on every form.
+ // Current menu not found, add it to the menu tree
//
- 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;
+ CurrentMenu = UiAddMenuList (gCurrentSelection->Handle, &gCurrentSelection->FormSetGuid,
+ gCurrentSelection->FormId, gCurrentSelection->QuestionId);
+ ASSERT (CurrentMenu != NULL);
+ }
+ gCurrentSelection->CurrentMenu = CurrentMenu;
- 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);
+ //
+ // Find currrent highlight statement.
+ //
+ if (gCurrentSelection->QuestionId == 0) {
+ //
+ // Highlight not specified, fetch it from cached menu
+ //
+ gCurrentSelection->QuestionId = CurrentMenu->QuestionId;
+ }
- 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);
- }
+ //
+ // Evaluate all the Expressions in this Form
+ //
+ Status = EvaluateFormExpressions (gCurrentSelection->FormSet, gCurrentSelection->Form);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
- 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;
+ UpdateDisplayFormData ();
- default:
- break;
+ //
+ // 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;
}
+
+ //
+ // 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);
+
+ Status = ProcessUserInput (&UserInput, ChangeHighlight);
+
+ FreeDisplayFormData();
+
+ return Status;
}
/**
@@ -920,60 +1715,136 @@ FormUpdateNotify (
}
/**
- check whether the formset need to update the NV.
+ Update the NV flag info for this form set.
@param FormSet FormSet data structure.
- @retval TRUE Need to update the NV.
- @retval FALSE No need to update the NV.
**/
-BOOLEAN
-IsNvUpdateRequired (
+BOOLEAN
+IsNvUpdateRequiredForFormSet (
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);
- if (Form->NvUpdateRequired ) {
- return TRUE;
+ 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) {
+ return TRUE;
+ }
+
+ Link = GetNextNode (&Form->StatementListHead, Link);
+ }
+
return FALSE;
}
/**
- check whether the formset need to update the NV.
+ Check whether the storage data for current form set is changed.
- @param FormSet FormSet data structure.
- @param SetValue Whether set new value or clear old value.
+ @param FormSet FormSet data structure.
+ @retval TRUE Data is changed.
+ @retval FALSE Data is not changed.
**/
-VOID
-UpdateNvInfoInForm (
- IN FORM_BROWSER_FORMSET *FormSet,
- IN BOOLEAN SetValue
+BOOLEAN
+IsStorageDataChangedForFormSet (
+ IN FORM_BROWSER_FORMSET *FormSet
)
{
LIST_ENTRY *Link;
- FORM_BROWSER_FORM *Form;
-
- Link = GetFirstNode (&FormSet->FormListHead);
- while (!IsNull (&FormSet->FormListHead, Link)) {
- Form = FORM_BROWSER_FORM_FROM_LINK (Link);
+ FORMSET_STORAGE *Storage;
+ BROWSER_STORAGE *BrowserStorage;
+ CHAR16 *ConfigRespNew;
+ CHAR16 *ConfigRespOld;
+ BOOLEAN RetVal;
- Form->NvUpdateRequired = SetValue;
+ RetVal = FALSE;
+ ConfigRespNew = NULL;
+ ConfigRespOld = NULL;
- Link = GetNextNode (&FormSet->FormListHead, Link);
+ //
+ // 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;
+
+ FreePool (ConfigRespOld);
+ ConfigRespOld = NULL;
+
+ if (RetVal) {
+ break;
+ }
}
+
+ return RetVal;
}
+
/**
Find menu which will show next time.
@@ -981,170 +1852,92 @@ UpdateNvInfoInForm (
about the Selection, form and formset to be displayed.
On output, Selection return the screen item that is selected
by user.
- @param Repaint Whether need to repaint the menu.
- @param NewLine Whether need to show at new line.
+ @param SettingLevel Input Settting level, if it is FormLevel, just exit current form.
+ else, we need to exit current formset.
- @retval TRUE Need return.
- @retval FALSE No need to return.
+ @retval TRUE Exit current form.
+ @retval FALSE User press ESC and keep in current form.
**/
BOOLEAN
FindNextMenu (
- IN OUT UI_MENU_SELECTION *Selection,
- IN BOOLEAN *Repaint,
- IN BOOLEAN *NewLine
+ IN OUT UI_MENU_SELECTION *Selection,
+ IN BROWSER_SETTING_SCOPE SettingLevel
)
{
- UI_MENU_LIST *CurrentMenu;
- CHAR16 YesResponse;
- CHAR16 NoResponse;
- EFI_INPUT_KEY Key;
- BROWSER_SETTING_SCOPE Scope;
+ FORM_ENTRY_INFO *CurrentMenu;
+ FORM_ENTRY_INFO *ParentMenu;
+ BROWSER_SETTING_SCOPE Scope;
CurrentMenu = Selection->CurrentMenu;
+ ParentMenu = NULL;
+ Scope = FormSetLevel;
- if (CurrentMenu != NULL && CurrentMenu->Parent != NULL) {
+ if (CurrentMenu != NULL && (ParentMenu = UiFindParentMenu(CurrentMenu)) != NULL) {
//
// we have a parent, so go to the parent menu
//
- 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) {
+ if (CompareGuid (&CurrentMenu->FormSetGuid, &ParentMenu->FormSetGuid)) {
+ if (SettingLevel == FormSetLevel) {
//
- // User hits the ESC key, Ingore.
+ // Find a menu which has different formset guid with current.
//
- if (Repaint != NULL) {
- *Repaint = TRUE;
- }
- if (NewLine != NULL) {
- *NewLine = TRUE;
+ while (CompareGuid (&CurrentMenu->FormSetGuid, &ParentMenu->FormSetGuid)) {
+ CurrentMenu = ParentMenu;
+ if ((ParentMenu = UiFindParentMenu(CurrentMenu)) == NULL) {
+ break;
+ }
}
- 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);
+ if (ParentMenu != NULL) {
+ Scope = FormSetLevel;
+ }
} else {
- //
- // If the user hits the NoResponse key
- //
- DiscardForm (Selection->FormSet, Selection->Form, Scope);
+ Scope = FormLevel;
}
+ } else {
+ Scope = FormSetLevel;
}
-
- Selection->Statement = NULL;
-
- Selection->FormId = CurrentMenu->Parent->FormId;
- Selection->QuestionId = CurrentMenu->Parent->QuestionId;
-
- //
- // Clear highlight record for this menu
- //
- CurrentMenu->QuestionId = 0;
- 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;
}
//
- // We are going to leave current FormSet, so check uncommited data in this FormSet
+ // Form Level Check whether the data is changed.
//
- 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;
+ if ((gBrowserSettingScope == FormLevel && IsNvUpdateRequiredForForm (Selection->Form)) ||
+ (gBrowserSettingScope == FormSetLevel && IsNvUpdateRequiredForFormSet(Selection->FormSet) && Scope == FormSetLevel)) {
+ if (!ProcessChangedData(Selection, Scope)) {
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);
+ if (ParentMenu != NULL) {
+ //
+ // ParentMenu is found. Then, go to it.
+ //
+ if (Scope == FormLevel) {
+ Selection->Action = UI_ACTION_REFRESH_FORM;
} else {
- //
- // If the user hits the NoResponse key
- //
- DiscardForm (Selection->FormSet, Selection->Form, FormSetLevel);
+ Selection->Action = UI_ACTION_REFRESH_FORMSET;
+ CopyMem (&Selection->FormSetGuid, &ParentMenu->FormSetGuid, sizeof (EFI_GUID));
+ Selection->Handle = ParentMenu->HiiHandle;
}
- }
- Selection->Statement = NULL;
- if (CurrentMenu != NULL) {
+ Selection->Statement = NULL;
+
+ Selection->FormId = ParentMenu->FormId;
+ Selection->QuestionId = ParentMenu->QuestionId;
+
+ //
+ // Clear highlight record for this menu
+ //
CurrentMenu->QuestionId = 0;
+ return FALSE;
}
+ //
+ // Current in root page, exit the SendForm
+ //
Selection->Action = UI_ACTION_EXIT;
+
return TRUE;
}
@@ -1244,18 +2037,19 @@ ProcessCallBackFunction (
if (Action == EFI_BROWSER_ACTION_CHANGED) {
switch (ActionRequest) {
case EFI_BROWSER_ACTION_REQUEST_RESET:
+ DiscardFormIsRequired = TRUE;
gResetRequired = TRUE;
- Selection->Action = UI_ACTION_EXIT;
+ NeedExit = TRUE;
break;
case EFI_BROWSER_ACTION_REQUEST_SUBMIT:
SubmitFormIsRequired = TRUE;
- Selection->Action = UI_ACTION_EXIT;
+ NeedExit = TRUE;
break;
case EFI_BROWSER_ACTION_REQUEST_EXIT:
DiscardFormIsRequired = TRUE;
- Selection->Action = UI_ACTION_EXIT;
+ NeedExit = TRUE;
break;
case EFI_BROWSER_ACTION_REQUEST_FORM_SUBMIT_EXIT:
@@ -1266,7 +2060,7 @@ ProcessCallBackFunction (
case EFI_BROWSER_ACTION_REQUEST_FORM_DISCARD_EXIT:
DiscardFormIsRequired = TRUE;
- SettingLevel = FormLevel;
+ SettingLevel = FormLevel;
NeedExit = TRUE;
break;
@@ -1319,7 +2113,7 @@ ProcessCallBackFunction (
}
if (NeedExit) {
- FindNextMenu (Selection, NULL, NULL);
+ FindNextMenu (Selection, SettingLevel);
}
return Status;
@@ -1399,9 +2193,7 @@ SetupBrowser (
EFI_HANDLE NotifyHandle;
FORM_BROWSER_STATEMENT *Statement;
EFI_HII_CONFIG_ACCESS_PROTOCOL *ConfigAccess;
- EFI_INPUT_KEY Key;
- gMenuRefreshHead = NULL;
ConfigAccess = Selection->FormSet->ConfigAccess;
//
@@ -1422,21 +2214,17 @@ SetupBrowser (
//
// Initialize current settings of Questions in this FormSet
//
- Status = InitializeCurrentSetting (Selection->FormSet);
- if (EFI_ERROR (Status)) {
- goto Done;
- }
+ InitializeCurrentSetting (Selection->FormSet);
//
- // Update gOldFormSet on maintain back up FormSet list.
- // And, make gOldFormSet point to current FormSet.
+ // Initilize Action field.
//
- if (gOldFormSet != NULL) {
- RemoveEntryList (&gOldFormSet->Link);
- DestroyFormSet (gOldFormSet);
- }
- gOldFormSet = Selection->FormSet;
- InsertTailList (&gBrowserFormSetList, &gOldFormSet->Link);
+ Selection->Action = UI_ACTION_REFRESH_FORM;
+
+ //
+ // Clean the mCurFakeQestId value is formset refreshed.
+ //
+ mCurFakeQestId = 0;
do {
//
@@ -1479,10 +2267,7 @@ SetupBrowser (
//
// Form is suppressed.
//
- do {
- CreateDialog (4, TRUE, 0, NULL, &Key, gEmptyString, gFormSuppress, gPressEnter, gEmptyString);
- } while (Key.UnicodeChar != CHAR_CARRIAGE_RETURN);
-
+ gBrowserStatus = BROWSER_FORM_SUPPRESS;
Status = EFI_NOT_FOUND;
goto Done;
}
@@ -1497,7 +2282,6 @@ SetupBrowser (
((Selection->Handle != mCurrentHiiHandle) ||
(!CompareGuid (&Selection->FormSetGuid, &mCurrentFormSetGuid)) ||
(Selection->FormId != mCurrentFormId))) {
-
//
// Keep current form information
//
@@ -1511,12 +2295,6 @@ SetupBrowser (
}
//
- // 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
//
if (mHiiPackageListUpdated) {
@@ -1535,12 +2313,6 @@ SetupBrowser (
}
//
- // 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
//
if (mHiiPackageListUpdated) {
@@ -1550,14 +2322,9 @@ SetupBrowser (
}
//
- // Displays the Header and Footer borders
- //
- DisplayPageFrame (Selection);
-
- //
// Display form
//
- Status = DisplayForm (Selection);
+ Status = DisplayForm ();
if (EFI_ERROR (Status)) {
goto Done;
}
@@ -1567,20 +2334,16 @@ 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 && Selection->Action != UI_ACTION_EXIT) {
+ Status = ProcessCallBackFunction(Selection, Statement, EFI_BROWSER_ACTION_CHANGING, FALSE);
+ if (Statement->Operand == EFI_IFR_REF_OP) {
//
// Process dynamic update ref opcode.
//
if (!EFI_ERROR (Status)) {
- Status = ProcessGotoOpCode(Statement, Selection, NULL, NULL);
+ Status = ProcessGotoOpCode(Statement, Selection);
}
//
@@ -1602,6 +2365,27 @@ 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
deleted file mode 100644
index eeadf24..0000000
--- a/MdeModulePkg/Universal/SetupBrowserDxe/Print.c
+++ /dev/null
@@ -1,272 +0,0 @@
-/** @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.<BR>
-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
deleted file mode 100644
index 181afec..0000000
--- a/MdeModulePkg/Universal/SetupBrowserDxe/ProcessOptions.c
+++ /dev/null
@@ -1,1042 +0,0 @@
-/** @file
-Implementation for handling the User Interface option processing.
-
-
-Copyright (c) 2004 - 2012, Intel Corporation. All rights reserved.<BR>
-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>
- //
- 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)) {
- 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;
- }
-}
-
-
-/**
- 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;
- BOOLEAN Suppress;
- 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);
- SetArrayData (ValueArray, ValueType, Index2, Option->Value.Value.u64);
- Index2++;
- Link = GetNextNode (&Question->OptionListHead, Link);
- }
- 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;
- }
-
- Suppress = FALSE;
- if ((OneOfOption->SuppressExpression != NULL) &&
- (EvaluateExpressionList(OneOfOption->SuppressExpression, FALSE, NULL, NULL) == ExpressSuppress)) {
- //
- // This option is suppressed
- //
- Suppress = TRUE;
- }
-
- if (!Suppress) {
- 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;
- }
-
- if ((OneOfOption->SuppressExpression != NULL) &&
- ((EvaluateExpressionList(OneOfOption->SuppressExpression, FALSE, NULL, NULL) == ExpressSuppress))) {
- //
- // This option is suppressed
- //
- Suppress = TRUE;
- } else {
- Suppress = FALSE;
- }
-
- if (Suppress) {
- //
- // Current selected option happen to be suppressed,
- // enforce to select on a non-suppressed option
- //
- Link = GetFirstNode (&Question->OptionListHead);
- while (!IsNull (&Question->OptionListHead, Link)) {
- OneOfOption = QUESTION_OPTION_FROM_LINK (Link);
-
- if ((OneOfOption->SuppressExpression == NULL) ||
- (EvaluateExpressionList(OneOfOption->SuppressExpression, FALSE, NULL, NULL) == ExpressFalse)) {
- Suppress = FALSE;
- CopyMem (QuestionValue, &OneOfOption->Value, sizeof (EFI_HII_VALUE));
- SetQuestionValue (Selection->FormSet, Selection->Form, Question, GetSetValueWithEditBuffer);
- UpdateStatusBar (Selection, NV_UPDATE_REQUIRED, Question->QuestionFlags, TRUE);
- gST->ConOut->SetAttribute (gST->ConOut, PcdGet8 (PcdBrowserFieldTextColor) | FIELD_BACKGROUND);
- break;
- }
-
- Link = GetNextNode (&Question->OptionListHead, Link);
- }
- }
-
- if (!Suppress) {
- 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 9e8f6e4..ba72d12 100644
--- a/MdeModulePkg/Universal/SetupBrowserDxe/Setup.c
+++ b/MdeModulePkg/Universal/SetupBrowserDxe/Setup.c
@@ -26,167 +26,281 @@ 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;
-EFI_HII_HANDLE gHiiHandle;
-UINT16 gDirection;
-EFI_SCREEN_DESCRIPTOR gScreenDimensions;
+BOOLEAN gExitRequired;
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 *gAreYouSure;
-CHAR16 *gYesResponse;
-CHAR16 *gNoResponse;
-CHAR16 *gMiniString;
-CHAR16 *gPlusString;
-CHAR16 *gMinusString;
-CHAR16 *gAdjustNumber;
-CHAR16 *gSaveChanges;
-CHAR16 *gOptionMismatch;
-CHAR16 *gFormSuppress;
-CHAR16 *gProtocolNotFound;
-
CHAR16 *mUnknownString = L"!";
-CHAR16 gPromptBlockWidth;
-CHAR16 gOptionBlockWidth;
-CHAR16 gHelpBlockWidth;
-
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}
-};
-FORM_BROWSER_FORMSET *gOldFormSet = NULL;
+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.
+
+**/
+FORM_ENTRY_INFO *
+UiAddMenuList (
+ IN EFI_HII_HANDLE HiiHandle,
+ IN EFI_GUID *FormSetGuid,
+ IN UINT16 FormId,
+ IN UINT16 QuestionId
+ )
+{
+ FORM_ENTRY_INFO *MenuList;
+
+ MenuList = AllocateZeroPool (sizeof (FORM_ENTRY_INFO));
+ if (MenuList == NULL) {
+ return NULL;
+ }
+
+ MenuList->Signature = FORM_ENTRY_INFO_SIGNATURE;
+
+ MenuList->HiiHandle = HiiHandle;
+ CopyMem (&MenuList->FormSetGuid, FormSetGuid, sizeof (EFI_GUID));
+ MenuList->FormId = FormId;
+ MenuList->QuestionId = QuestionId;
-FUNCTIION_KEY_SETTING gFunctionKeySettingTable[] = {
//
- // Boot Manager
+ // If parent is not specified, it is the root Form of a Formset
//
- {
- {
- 0x847bc3fe,
- 0xb974,
- 0x446d,
- {
- 0x94,
- 0x49,
- 0x5a,
- 0xd5,
- 0x41,
- 0x2e,
- 0x99,
- 0x3b
+ 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;
+ }
+ }
}
- },
- NONE_FUNCTION_KEY_SETTING
- },
+ }
+ }
+
+ 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;
+
//
- // Device Manager
+ // Get all the Hii handles
//
- {
- {
- 0x3ebfa8e6,
- 0x511d,
- 0x4b5b,
- {
- 0xa9,
- 0x5f,
- 0xfb,
- 0x38,
- 0x26,
- 0xf,
- 0x1c,
- 0x27
- }
- },
- NONE_FUNCTION_KEY_SETTING
- },
+ HiiHandles = HiiGetHiiHandles (NULL);
+ ASSERT (HiiHandles != NULL);
+
//
- // BMM FormSet.
+ // Search for formset of each class type
//
- {
- {
- 0x642237c7,
- 0x35d4,
- 0x472d,
- {
- 0x83,
- 0x65,
- 0x12,
- 0xe0,
- 0xcc,
- 0xf2,
- 0x7a,
- 0x22
- }
- },
- NONE_FUNCTION_KEY_SETTING
- },
+ 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;
+ }
+ }
+
//
- // BMM File Explorer FormSet.
+ // Free resources, and restore gOldFormSet and gClassOfVfr
//
- {
- {
- 0x1f2d63e1,
- 0xfebd,
- 0x4dc7,
- {
- 0x9c,
- 0xc5,
- 0xba,
- 0x2b,
- 0x1c,
- 0xef,
- 0x9c,
- 0x5b
- }
- },
- NONE_FUNCTION_KEY_SETTING
- },
-};
+ FreePool (HiiHandles);
+}
/**
This is the routine which an external caller uses to direct the browser
@@ -229,21 +343,14 @@ SendForm (
UI_MENU_SELECTION *Selection;
UINTN Index;
FORM_BROWSER_FORMSET *FormSet;
- LIST_ENTRY *Link;
+ FORM_ENTRY_INFO *MenuList;
//
- // Calculate total number of Register HotKeys.
+ // If EDKII_FORM_DISPLAY_ENGINE_PROTOCOL not found, return EFI_UNSUPPORTED.
//
- Index = 0;
- Link = GetFirstNode (&gBrowserHotKeyList);
- while (!IsNull (&gBrowserHotKeyList, Link)) {
- Link = GetNextNode (&gBrowserHotKeyList, Link);
- Index ++;
+ if (mFormDisplay == NULL) {
+ return EFI_UNSUPPORTED;
}
- //
- // Show three HotKeys help information on one ROW.
- //
- gFooterHeight = FOOTER_HEIGHT + (Index / 3);
//
// Save globals used by SendForm()
@@ -251,67 +358,10 @@ SendForm (
SaveBrowserContext ();
gResetRequired = FALSE;
- 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 ();
-
- gFunctionKeySetting = ENABLE_FUNCTION_KEY_SETTING;
-
- //
- // Ensure we are in Text mode
- //
- gST->ConOut->SetAttribute (gST->ConOut, EFI_TEXT_ATTR (EFI_LIGHTGRAY, EFI_BLACK));
+ gExitRequired = FALSE;
+ Status = EFI_SUCCESS;
+ gEmptyString = L"";
+ gDisplayFormData.ScreenDimensions = (EFI_SCREEN_DESCRIPTOR *) ScreenDimensions;
for (Index = 0; Index < HandleCount; Index++) {
Selection = AllocateZeroPool (sizeof (UI_MENU_SELECTION));
@@ -332,7 +382,7 @@ SendForm (
//
// Initialize internal data structures of FormSet
//
- Status = InitializeFormSet (Selection->Handle, &Selection->FormSetGuid, FormSet, TRUE);
+ Status = InitializeFormSet (Selection->Handle, &Selection->FormSetGuid, FormSet);
if (EFI_ERROR (Status) || IsListEmpty (&FormSet->FormListHead)) {
DestroyFormSet (FormSet);
break;
@@ -340,11 +390,6 @@ SendForm (
Selection->FormSet = FormSet;
//
- // Try to find pre FormSet in the maintain backup list.
- //
- gOldFormSet = GetFormSetFromHiiHandle (Selection->Handle);
-
- //
// Display this formset
//
gCurrentSelection = Selection;
@@ -353,27 +398,36 @@ SendForm (
gCurrentSelection = NULL;
- if (EFI_ERROR (Status)) {
- break;
- }
-
- } while (Selection->Action == UI_ACTION_REFRESH_FORMSET);
-
- 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);
+ if (!IsNvUpdateRequiredForFormSet (FormSet) && !IsStorageDataChangedForFormSet(FormSet)) {
+ CleanBrowserStorage(FormSet);
+ RemoveEntryList (&FormSet->Link);
+ DestroyFormSet (FormSet);
}
- gOldFormSet = NULL;
- }
+
+ 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;
+
+ gBrowserStatus = BROWSER_SUCCESS;
+ gErrorInfo = NULL;
+
+ mFormDisplay->FormDisplay (&gDisplayFormData, NULL);
+ }
+
if (ActionRequest != NULL) {
*ActionRequest = EFI_BROWSER_ACTION_REQUEST_NONE;
if (gResetRequired) {
@@ -381,12 +435,17 @@ SendForm (
}
}
- FreeBrowserStrings ();
+ mFormDisplay->ExitDisplay();
- gST->ConOut->SetAttribute (gST->ConOut, EFI_TEXT_ATTR (EFI_LIGHTGRAY, EFI_BLACK));
- gST->ConOut->ClearScreen (gST->ConOut);
+ //
+ // 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);
+ }
-Done:
//
// Restore globals used by SendForm()
//
@@ -395,10 +454,93 @@ Done:
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 <ConfigResp>
+ //
+ Status = StorageToConfigResp (Storage, &ConfigResp, Storage->ConfigRequest, TRUE);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ //
+ // Skip <ConfigHdr> and '&' to point to <ConfigBody> 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 <ConfigResp>
+ //
+ 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 function is called by a callback handler to retrieve uncommitted state
- data from the browser.
+ This routine called this service in the browser to retrieve or set certain uncommitted
+ state information that resides in the open formsets.
@param This A pointer to the EFI_FORM_BROWSER2_PROTOCOL
instance.
@@ -436,60 +578,69 @@ BrowserCallback (
{
EFI_STATUS Status;
LIST_ENTRY *Link;
- FORMSET_STORAGE *Storage;
+ BROWSER_STORAGE *Storage;
+ FORMSET_STORAGE *FormsetStorage;
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;
}
- if (gCurrentSelection == NULL) {
- return EFI_NOT_READY;
- }
-
- Storage = NULL;
- ConfigResp = NULL;
- FormSet = gCurrentSelection->FormSet;
+ TotalSize = *ResultsDataSize;
+ Storage = NULL;
+ Found = FALSE;
+ Status = EFI_SUCCESS;
//
- // Find target storage
+ // If set browser data, pre load all hii formset to avoid set the varstore which is not
+ // saved in browser.
//
- Link = GetFirstNode (&FormSet->StorageListHead);
- if (IsNull (&FormSet->StorageListHead, Link)) {
- return EFI_UNSUPPORTED;
+ if (!RetrieveData && (gBrowserSettingScope == SystemLevel)) {
+ LoadAllHiiFormset();
}
if (VariableGuid != NULL) {
//
- // Try to find target storage
+ // Try to find target storage in the current formset.
//
- Found = FALSE;
- while (!IsNull (&FormSet->StorageListHead, Link)) {
- Storage = FORMSET_STORAGE_FROM_LINK (Link);
- Link = GetNextNode (&FormSet->StorageListHead, Link);
+ 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;
+ }
- 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 (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 (StrCmp (Storage->BrowserStorage->Name, (CHAR16 *) VariableName) != 0) {
- continue;
- }
+ if (StrCmp (Storage->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) {
@@ -499,65 +650,62 @@ BrowserCallback (
//
// GUID/Name is not specified, take the first storage in FormSet
//
- Storage = FORMSET_STORAGE_FROM_LINK (Link);
- }
-
- if (RetrieveData) {
- //
- // Skip if there is no RequestElement
- //
- if (Storage->ElementCount == 0) {
- return EFI_SUCCESS;
+ if (gCurrentSelection == NULL) {
+ return EFI_NOT_READY;
}
//
// Generate <ConfigResp>
//
- Status = StorageToConfigResp (Storage->BrowserStorage, &ConfigResp, Storage->ConfigRequest);
+ FormSet = gCurrentSelection->FormSet;
+ Link = GetFirstNode (&FormSet->StorageListHead);
+ if (IsNull (&FormSet->StorageListHead, Link)) {
+ return EFI_UNSUPPORTED;
+ }
+
+ FormsetStorage = FORMSET_STORAGE_FROM_LINK (Link);
+
+ Status = ProcessStorage (&TotalSize, &ResultsData, RetrieveData, FormsetStorage->BrowserStorage);
if (EFI_ERROR (Status)) {
return Status;
}
+ }
- //
- // Skip <ConfigHdr> and '&' to point to <ConfigBody>
- //
- StrPtr = ConfigResp + StrLen (Storage->BrowserStorage->ConfigHdr) + 1;
+ if (RetrieveData) {
+ Status = TotalSize <= *ResultsDataSize ? EFI_SUCCESS : EFI_BUFFER_TOO_SMALL;
+ *ResultsDataSize = TotalSize;
+ }
+
+ return Status;
- BufferSize = StrSize (StrPtr);
- if (*ResultsDataSize < BufferSize) {
- *ResultsDataSize = BufferSize;
+}
- FreePool (ConfigResp);
- return EFI_BUFFER_TOO_SMALL;
- }
- *ResultsDataSize = BufferSize;
- CopyMem (ResultsData, StrPtr, BufferSize);
+/**
+ Callback function for SimpleTextInEx protocol install events
- FreePool (ConfigResp);
- } else {
- //
- // Prepare <ConfigResp>
- //
- TmpSize = StrLen (ResultsData);
- BufferSize = (TmpSize + StrLen (Storage->BrowserStorage->ConfigHdr) + 2) * sizeof (CHAR16);
- ConfigResp = AllocateZeroPool (BufferSize);
- ASSERT (ConfigResp != NULL);
+ @param Event the event that is signaled.
+ @param Context not used here.
- StrCpy (ConfigResp, Storage->BrowserStorage->ConfigHdr);
- StrCat (ConfigResp, L"&");
- StrCat (ConfigResp, ResultsData);
+**/
+VOID
+EFIAPI
+FormDisplayCallback (
+ IN EFI_EVENT Event,
+ IN VOID *Context
+ )
+{
+ EFI_STATUS Status;
- //
- // Update Browser uncommited data
- //
- Status = ConfigRespToStorage (Storage->BrowserStorage, ConfigResp);
- if (EFI_ERROR (Status)) {
- return Status;
- }
+ if (mFormDisplay != NULL) {
+ return;
}
- return EFI_SUCCESS;
+ Status = gBS->LocateProtocol (
+ &gEdkiiFormDisplayEngineProtocolGuid,
+ NULL,
+ (VOID **) &mFormDisplay
+ );
}
/**
@@ -578,8 +726,7 @@ InitializeSetup (
)
{
EFI_STATUS Status;
- EFI_INPUT_KEY DefaultHotKey;
- EFI_STRING HelpString;
+ VOID *Registration;
//
// Locate required Hii relative protocols
@@ -592,13 +739,6 @@ InitializeSetup (
ASSERT_EFI_ERROR (Status);
Status = gBS->LocateProtocol (
- &gEfiHiiStringProtocolGuid,
- NULL,
- (VOID **) &mHiiString
- );
- ASSERT_EFI_ERROR (Status);
-
- Status = gBS->LocateProtocol (
&gEfiHiiConfigRoutingProtocolGuid,
NULL,
(VOID **) &mHiiConfigRouting
@@ -612,30 +752,6 @@ InitializeSetup (
);
//
- // 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
//
mPrivateData.Handle = NULL;
@@ -648,34 +764,45 @@ InitializeSetup (
ASSERT_EFI_ERROR (Status);
//
- // 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
+ // Install FormBrowserEx2 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,
EFI_NATIVE_INTERFACE,
&mPrivateData.FormBrowserEx
);
ASSERT_EFI_ERROR (Status);
- return Status;
+ InitializeDisplayFormData ();
+
+ Status = gBS->LocateProtocol (
+ &gEdkiiFormDisplayEngineProtocolGuid,
+ NULL,
+ (VOID **) &mFormDisplay
+ );
+
+ if (EFI_ERROR (Status)) {
+ EfiCreateProtocolNotifyEvent (
+ &gEdkiiFormDisplayEngineProtocolGuid,
+ TPL_CALLBACK,
+ FormDisplayCallback,
+ NULL,
+ &Registration
+ );
+ }
+
+ return EFI_SUCCESS;
}
@@ -811,58 +938,6 @@ NewStringCat (
*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);
-
- if (SyncOrRestore) {
- NewStringCpy (&Node->Value, Node->EditValue);
- } else {
- NewStringCpy (&Node->EditValue, Node->Value);
- }
-
- Link = GetNextNode (&Storage->NameValueListHead, Link);
- }
- break;
-
- case EFI_HII_VARSTORE_EFI_VARIABLE:
- default:
- break;
- }
-}
-
-
/**
Get Value for given Name from a NameValue Storage.
@@ -919,6 +994,7 @@ 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.
@@ -926,10 +1002,11 @@ GetValueByName (
**/
EFI_STATUS
SetValueByName (
- IN BROWSER_STORAGE *Storage,
- IN CHAR16 *Name,
- IN CHAR16 *Value,
- IN GET_SET_QUESTION_VALUE_WITH SetValueTo
+ IN BROWSER_STORAGE *Storage,
+ IN CHAR16 *Name,
+ IN CHAR16 *Value,
+ IN GET_SET_QUESTION_VALUE_WITH SetValueTo,
+ OUT NAME_VALUE_NODE **ReturnNode
)
{
LIST_ENTRY *Link;
@@ -960,6 +1037,11 @@ SetValueByName (
} else {
Node->Value = Buffer;
}
+
+ if (ReturnNode != NULL) {
+ *ReturnNode = Node;
+ }
+
return EFI_SUCCESS;
}
@@ -976,6 +1058,7 @@ SetValueByName (
@param Storage The Storage to be conveted.
@param ConfigResp The returned <ConfigResp>.
@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.
@@ -985,23 +1068,26 @@ EFI_STATUS
StorageToConfigResp (
IN BROWSER_STORAGE *Storage,
IN CHAR16 **ConfigResp,
- IN CHAR16 *ConfigRequest
+ IN CHAR16 *ConfigRequest,
+ IN BOOLEAN GetEditBuf
)
{
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,
- Storage->EditBuffer,
+ SourceBuf,
Storage->Size,
ConfigResp,
&Progress
@@ -1020,7 +1106,11 @@ StorageToConfigResp (
NewStringCat (ConfigResp, L"&");
NewStringCat (ConfigResp, Node->Name);
NewStringCat (ConfigResp, L"=");
- NewStringCat (ConfigResp, Node->EditValue);
+ if (GetEditBuf) {
+ NewStringCat (ConfigResp, Node->EditValue);
+ } else {
+ NewStringCat (ConfigResp, Node->Value);
+ }
}
Link = GetNextNode (&Storage->NameValueListHead, Link);
}
@@ -1101,7 +1191,7 @@ ConfigRespToStorage (
if (StrPtr != NULL) {
*StrPtr = 0;
}
- SetValueByName (Storage, Name, Value, GetSetValueWithEditBuffer);
+ SetValueByName (Storage, Name, Value, GetSetValueWithEditBuffer, NULL);
}
break;
@@ -1527,7 +1617,7 @@ GetQuestionValue (
if (IsBufferStorage) {
CopyMem (Storage->EditBuffer + Question->VarStoreInfo.VarOffset, Dst, StorageWidth);
} else {
- SetValueByName (Storage, Question->VariableName, Value, GetSetValueWithEditBuffer);
+ SetValueByName (Storage, Question->VariableName, Value, GetSetValueWithEditBuffer, NULL);
}
if (Result != NULL) {
@@ -1577,8 +1667,10 @@ SetQuestionValue (
CHAR16 *TemName;
CHAR16 *TemString;
UINTN Index;
+ NAME_VALUE_NODE *Node;
Status = EFI_SUCCESS;
+ Node = NULL;
if (SetValueTo >= GetSetValueWithMax) {
return EFI_INVALID_PARAMETER;
@@ -1713,6 +1805,14 @@ 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) {
//
@@ -1744,8 +1844,19 @@ SetQuestionValue (
}
}
- Status = SetValueByName (Storage, Question->VariableName, Value, SetValueTo);
+ Status = SetValueByName (Storage, Question->VariableName, Value, SetValueTo, &Node);
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) {
@@ -1864,12 +1975,12 @@ SetQuestionValue (
/**
- Perform inconsistent check for a Form.
+ Perform nosubmitif 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: InConsistent or NoSubmit
+ @param Type Validation type: NoSubmit
@retval EFI_SUCCESS Form validation pass.
@retval other Form validation failed.
@@ -1887,12 +1998,9 @@ ValidateQuestion (
LIST_ENTRY *Link;
LIST_ENTRY *ListHead;
EFI_STRING PopUp;
- EFI_INPUT_KEY Key;
FORM_EXPRESSION *Expression;
- if (Type == EFI_HII_EXPRESSION_INCONSISTENT_IF) {
- ListHead = &Question->InconsistentListHead;
- } else if (Type == EFI_HII_EXPRESSION_NO_SUBMIT_IF) {
+ if (Type == EFI_HII_EXPRESSION_NO_SUBMIT_IF) {
ListHead = &Question->NoSubmitListHead;
} else {
return EFI_UNSUPPORTED;
@@ -1916,10 +2024,10 @@ ValidateQuestion (
//
if (Expression->Error != 0) {
PopUp = GetToken (Expression->Error, FormSet->HiiHandle);
- do {
- CreateDialog (4, TRUE, 0, NULL, &Key, gEmptyString, PopUp, gPressEnter, gEmptyString);
- } while (Key.UnicodeChar != CHAR_CARRIAGE_RETURN);
- FreePool (PopUp);
+ if (Type == EFI_HII_EXPRESSION_NO_SUBMIT_IF) {
+ gBrowserStatus = BROWSER_NO_SUBMIT_IF;
+ gErrorInfo = PopUp;
+ }
}
return EFI_NOT_READY;
@@ -1983,7 +2091,8 @@ NoSubmitCheck (
Fill storage's edit copy with settings requested from Configuration Driver.
@param FormSet FormSet data structure.
- @param ConfigInfo The config info related to this form.
+ @param Storage The storage which need to sync.
+ @param ConfigRequest The config request string which used to sync storage.
@param SyncOrRestore Sync the buffer to editbuffer or Restore the
editbuffer to buffer
if TRUE, copy the editbuffer to the buffer.
@@ -1993,10 +2102,11 @@ NoSubmitCheck (
**/
EFI_STATUS
-SynchronizeStorageForForm (
- IN FORM_BROWSER_FORMSET *FormSet,
- IN FORM_BROWSER_CONFIG_REQUEST *ConfigInfo,
- IN BOOLEAN SyncOrRestore
+SynchronizeStorage (
+ IN FORM_BROWSER_FORMSET *FormSet,
+ OUT BROWSER_STORAGE *Storage,
+ IN CHAR16 *ConfigRequest,
+ IN BOOLEAN SyncOrRestore
)
{
EFI_STATUS Status;
@@ -2010,57 +2120,52 @@ SynchronizeStorageForForm (
Status = EFI_SUCCESS;
Result = NULL;
- if (FormSet->ConfigAccess == NULL && ConfigInfo->Storage->Type != EFI_HII_VARSTORE_NAME_VALUE) {
- return EFI_NOT_FOUND;
- }
-
- 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 (Storage->Type == EFI_HII_VARSTORE_BUFFER ||
+ (Storage->Type == EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER)) {
+ BufferSize = Storage->Size;
if (SyncOrRestore) {
- Src = ConfigInfo->Storage->EditBuffer;
- Dst = ConfigInfo->Storage->Buffer;
+ Src = Storage->EditBuffer;
+ Dst = Storage->Buffer;
} else {
- Src = ConfigInfo->Storage->Buffer;
- Dst = ConfigInfo->Storage->EditBuffer;
+ Src = Storage->Buffer;
+ Dst = Storage->EditBuffer;
}
- Status = mHiiConfigRouting->BlockToConfig(
- mHiiConfigRouting,
- ConfigInfo->ConfigRequest,
- Src,
- BufferSize,
- &Result,
- &Progress
- );
- if (EFI_ERROR (Status)) {
- return Status;
- }
+ if (ConfigRequest != NULL) {
+ Status = mHiiConfigRouting->BlockToConfig(
+ mHiiConfigRouting,
+ ConfigRequest,
+ Src,
+ BufferSize,
+ &Result,
+ &Progress
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
- Status = mHiiConfigRouting->ConfigToBlock (
- mHiiConfigRouting,
- Result,
- Dst,
- &BufferSize,
- &Progress
- );
- if (Result != NULL) {
- FreePool (Result);
+ Status = mHiiConfigRouting->ConfigToBlock (
+ mHiiConfigRouting,
+ Result,
+ Dst,
+ &BufferSize,
+ &Progress
+ );
+ if (Result != NULL) {
+ FreePool (Result);
+ }
+ } else {
+ CopyMem (Dst, Src, BufferSize);
}
- } else if (ConfigInfo->Storage->Type == EFI_HII_VARSTORE_NAME_VALUE) {
- Link = GetFirstNode (&ConfigInfo->Storage->NameValueListHead);
- while (!IsNull (&ConfigInfo->Storage->NameValueListHead, Link)) {
+ } 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);
- if (StrStr (ConfigInfo->ConfigRequest, Node->Name) != NULL) {
+ if ((ConfigRequest != NULL && StrStr (ConfigRequest, Node->Name) != NULL) ||
+ (ConfigRequest == NULL)) {
if (SyncOrRestore) {
NewStringCpy (&Node->Value, Node->EditValue);
} else {
@@ -2068,7 +2173,7 @@ SynchronizeStorageForForm (
}
}
- Link = GetNextNode (&ConfigInfo->Storage->NameValueListHead, Link);
+ Link = GetNextNode (&Storage->NameValueListHead, Link);
}
}
@@ -2091,20 +2196,9 @@ 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);
@@ -2118,45 +2212,10 @@ SendDiscardInfoToDriver (
continue;
}
- 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) {
+ if (!Question->ValueChanged) {
continue;
}
- ValueChanged = FALSE;
-
if (Question->HiiValue.Type == EFI_IFR_TYPE_BUFFER) {
TypeValue = (EFI_IFR_TYPE_VALUE *) Question->BufferValue;
} else {
@@ -2221,6 +2280,78 @@ 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).
@@ -2252,7 +2383,7 @@ DiscardForm (
return EFI_UNSUPPORTED;
}
- if (SettingScope == FormLevel && Form->NvUpdateRequired) {
+ if (SettingScope == FormLevel && IsNvUpdateRequiredForForm (Form)) {
ConfigInfo = NULL;
Link = GetFirstNode (&Form->ConfigRequestHead);
while (!IsNull (&Form->ConfigRequestHead, Link)) {
@@ -2273,7 +2404,7 @@ DiscardForm (
//
// Prepare <ConfigResp>
//
- SynchronizeStorageForForm(FormSet, ConfigInfo, FALSE);
+ SynchronizeStorage(FormSet, ConfigInfo->Storage, ConfigInfo->ConfigRequest, FALSE);
//
// Call callback with Changed type to inform the driver.
@@ -2281,8 +2412,8 @@ DiscardForm (
SendDiscardInfoToDriver (FormSet, Form);
}
- Form->NvUpdateRequired = FALSE;
- } else if (SettingScope == FormSetLevel && IsNvUpdateRequired(FormSet)) {
+ ValueChangeResetFlagUpdate (FALSE, NULL, Form);
+ } else if (SettingScope == FormSetLevel && IsNvUpdateRequiredForFormSet (FormSet)) {
//
// Discard Buffer storage or Name/Value storage
@@ -2303,7 +2434,7 @@ DiscardForm (
continue;
}
- SynchronizeStorage(Storage->BrowserStorage, FALSE);
+ SynchronizeStorage(FormSet, Storage->BrowserStorage, Storage->ConfigRequest, FALSE);
}
Link = GetFirstNode (&FormSet->FormListHead);
@@ -2317,7 +2448,7 @@ DiscardForm (
SendDiscardInfoToDriver (FormSet, Form);
}
- UpdateNvInfoInForm (FormSet, FALSE);
+ ValueChangeResetFlagUpdate(FALSE, FormSet, NULL);
} else if (SettingScope == SystemLevel) {
//
// System Level Discard.
@@ -2397,7 +2528,7 @@ SubmitForm (
return Status;
}
- if (SettingScope == FormLevel && Form->NvUpdateRequired) {
+ if (SettingScope == FormLevel && IsNvUpdateRequiredForForm (Form)) {
ConfigInfo = NULL;
Link = GetFirstNode (&Form->ConfigRequestHead);
while (!IsNull (&Form->ConfigRequestHead, Link)) {
@@ -2419,7 +2550,7 @@ SubmitForm (
//
// 1. Prepare <ConfigResp>
//
- Status = StorageToConfigResp (ConfigInfo->Storage, &ConfigResp, ConfigInfo->ConfigRequest);
+ Status = StorageToConfigResp (ConfigInfo->Storage, &ConfigResp, ConfigInfo->ConfigRequest, TRUE);
if (EFI_ERROR (Status)) {
return Status;
}
@@ -2495,14 +2626,14 @@ SubmitForm (
//
// 3. Config success, update storage shadow Buffer, only update the data belong to this form.
//
- SynchronizeStorageForForm(FormSet, ConfigInfo, TRUE);
+ SynchronizeStorage (FormSet, ConfigInfo->Storage, ConfigInfo->ConfigRequest, TRUE);
}
//
// 4. Update the NV flag.
//
- Form->NvUpdateRequired = FALSE;
- } else if (SettingScope == FormSetLevel && IsNvUpdateRequired(FormSet)) {
+ ValueChangeResetFlagUpdate(TRUE, NULL, Form);
+ } else if (SettingScope == FormSetLevel && IsNvUpdateRequiredForFormSet (FormSet)) {
//
// Submit Buffer storage or Name/Value storage
//
@@ -2526,7 +2657,7 @@ SubmitForm (
//
// 1. Prepare <ConfigResp>
//
- Status = StorageToConfigResp (Storage, &ConfigResp, FormSetStorage->ConfigRequest);
+ Status = StorageToConfigResp (Storage, &ConfigResp, FormSetStorage->ConfigRequest, TRUE);
if (EFI_ERROR (Status)) {
return Status;
}
@@ -2598,13 +2729,13 @@ SubmitForm (
//
// 3. Config success, update storage shadow Buffer
//
- SynchronizeStorage (Storage, TRUE);
+ SynchronizeStorage (FormSet, Storage, FormSetStorage->ConfigRequest, TRUE);
}
//
// 4. Update the NV flag.
//
- UpdateNvInfoInForm (FormSet, FALSE);
+ ValueChangeResetFlagUpdate(TRUE, FormSet, NULL);
} else if (SettingScope == SystemLevel) {
//
// System Level Save.
@@ -2860,6 +2991,138 @@ GetDefaultIdForCallBack (
}
}
+
+
+/**
+ 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;
+ }
+}
+
+/**
+ 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;
+}
+
+
/**
Reset Question to its default value.
@@ -3008,6 +3271,12 @@ GetQuestionDefault (
Link = GetFirstNode (&Question->OptionListHead);
while (!IsNull (&Question->OptionListHead, Link)) {
Option = QUESTION_OPTION_FROM_LINK (Link);
+ Link = GetNextNode (&Question->OptionListHead, Link);
+
+ if ((Option->SuppressExpression != NULL) &&
+ EvaluateExpressionList(Option->SuppressExpression, FALSE, NULL, NULL) != ExpressFalse) {
+ continue;
+ }
if (((DefaultId == EFI_HII_DEFAULT_CLASS_STANDARD) && ((Option->Flags & EFI_IFR_OPTION_DEFAULT) != 0)) ||
((DefaultId == EFI_HII_DEFAULT_CLASS_MANUFACTURING) && ((Option->Flags & EFI_IFR_OPTION_DEFAULT_MFG) != 0))
@@ -3016,8 +3285,6 @@ GetQuestionDefault (
return EFI_SUCCESS;
}
-
- Link = GetNextNode (&Question->OptionListHead, Link);
}
}
}
@@ -3063,10 +3330,18 @@ GetQuestionDefault (
//
if (ValueToOption (Question, HiiValue) == NULL) {
Link = GetFirstNode (&Question->OptionListHead);
- if (!IsNull (&Question->OptionListHead, Link)) {
+ while (!IsNull (&Question->OptionListHead, Link)) {
Option = QUESTION_OPTION_FROM_LINK (Link);
+ Link = GetNextNode (&Question->OptionListHead, Link);
+
+ if ((Option->SuppressExpression != NULL) &&
+ EvaluateExpressionList(Option->SuppressExpression, FALSE, NULL, NULL) != ExpressFalse) {
+ continue;
+ }
+
CopyMem (HiiValue, &Option->Value, sizeof (EFI_HII_VALUE));
Status = EFI_SUCCESS;
+ break;
}
}
break;
@@ -3080,6 +3355,12 @@ GetQuestionDefault (
while (!IsNull (&Question->OptionListHead, Link)) {
Status = EFI_SUCCESS;
Option = QUESTION_OPTION_FROM_LINK (Link);
+ Link = GetNextNode (&Question->OptionListHead, Link);
+
+ if ((Option->SuppressExpression != NULL) &&
+ EvaluateExpressionList(Option->SuppressExpression, FALSE, NULL, NULL) != ExpressFalse) {
+ continue;
+ }
SetArrayData (Question->BufferValue, Question->ValueType, Index, Option->Value.Value.u64);
@@ -3087,8 +3368,6 @@ GetQuestionDefault (
if (Index >= Question->MaxContainers) {
break;
}
-
- Link = GetNextNode (&Question->OptionListHead, Link);
}
break;
@@ -3135,11 +3414,7 @@ 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;
@@ -3209,10 +3484,6 @@ 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) {
@@ -3224,65 +3495,9 @@ ExtractDefault (
}
} else if (SettingScope == SystemLevel) {
//
- // 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
+ // Preload all Hii formset.
//
- 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
- //
- FreePool (HiiHandles);
- gOldFormSet = BackUpFormSet;
+ LoadAllHiiFormset();
//
// Set Default Value for each FormSet in the maintain list.
@@ -3301,6 +3516,81 @@ 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.
@@ -3334,7 +3624,11 @@ LoadFormConfig (
//
// Initialize local copy of Value for each Question
//
- Status = GetQuestionValue (FormSet, Form, Question, GetSetValueWithEditBuffer);
+ 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);
+ }
if (EFI_ERROR (Status)) {
return Status;
}
@@ -3374,6 +3668,11 @@ 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);
}
@@ -3417,6 +3716,11 @@ LoadFormSetConfig (
Link = GetNextNode (&FormSet->FormListHead, Link);
}
+ //
+ // Finished question initialization.
+ //
+ FormSet->QuestionInited = TRUE;
+
return EFI_SUCCESS;
}
@@ -3471,6 +3775,13 @@ 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
@@ -3545,6 +3856,7 @@ CleanBrowserStorage (
{
LIST_ENTRY *Link;
FORMSET_STORAGE *Storage;
+ CHAR16 *ConfigRequest;
Link = GetFirstNode (&FormSet->StorageListHead);
while (!IsNull (&FormSet->StorageListHead, Link)) {
@@ -3552,7 +3864,8 @@ 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_NAME_VALUE) &&
+ (Storage->BrowserStorage->Type != EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER)) {
continue;
}
@@ -3560,7 +3873,8 @@ CleanBrowserStorage (
continue;
}
- RemoveConfigRequest (Storage->BrowserStorage, Storage->ConfigRequest);
+ ConfigRequest = FormSet->QuestionInited ? Storage->ConfigRequest : Storage->ConfigElements;
+ RemoveConfigRequest (Storage->BrowserStorage, ConfigRequest);
}
}
@@ -3631,7 +3945,6 @@ 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.
@@ -3639,8 +3952,7 @@ AppendConfigRequest (
**/
BOOLEAN
ConfigRequestAdjust (
- IN FORMSET_STORAGE *Storage,
- OUT CHAR16 **ConfigRequest
+ IN FORMSET_STORAGE *Storage
)
{
CHAR16 *RequestElement;
@@ -3656,7 +3968,10 @@ ConfigRequestAdjust (
if (Storage->BrowserStorage->ConfigRequest == NULL) {
Storage->BrowserStorage->ConfigRequest = AllocateCopyPool (StrSize (Storage->ConfigRequest), Storage->ConfigRequest);
- *ConfigRequest = AllocateCopyPool (StrSize (Storage->ConfigRequest), Storage->ConfigRequest);
+ if (Storage->ConfigElements != NULL) {
+ FreePool (Storage->ConfigElements);
+ }
+ Storage->ConfigElements = AllocateCopyPool (StrSize (Storage->ConfigRequest), Storage->ConfigRequest);
return TRUE;
}
@@ -3725,7 +4040,10 @@ ConfigRequestAdjust (
}
if (RetVal) {
- *ConfigRequest = RetBuf;
+ if (Storage->ConfigElements != NULL) {
+ FreePool (Storage->ConfigElements);
+ }
+ Storage->ConfigElements = RetBuf;
} else {
FreePool (RetBuf);
}
@@ -3734,15 +4052,162 @@ ConfigRequestAdjust (
}
/**
+
+ 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.
-
**/
-EFI_STATUS
+VOID
LoadStorage (
IN FORM_BROWSER_FORMSET *FormSet,
IN FORMSET_STORAGE *Storage
@@ -3752,18 +4217,17 @@ LoadStorage (
EFI_STRING Progress;
EFI_STRING Result;
CHAR16 *StrPtr;
- CHAR16 *ConfigRequest;
- if (Storage->BrowserStorage->Type == EFI_HII_VARSTORE_EFI_VARIABLE) {
- return EFI_SUCCESS;
- }
+ 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_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,
@@ -3771,55 +4235,78 @@ LoadStorage (
(UINTN*)&Storage->BrowserStorage->Size,
Storage->BrowserStorage->EditBuffer
);
- }
- return Status;
- }
+ //
+ // 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);
+ }
- if (FormSet->ConfigAccess == NULL) {
- return EFI_NOT_FOUND;
- }
+ 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;
- if (Storage->ElementCount == 0) {
- //
- // Skip if there is no RequestElement
- //
- return EFI_SUCCESS;
- }
+ case EFI_HII_VARSTORE_BUFFER:
+ case EFI_HII_VARSTORE_NAME_VALUE:
+ //
+ // Skip if there is no RequestElement
+ //
+ if (Storage->ElementCount == 0) {
+ return;
+ }
- //
- // Adjust the ConfigRequest string, only the field not saved in BrowserStorage->AllConfig
- // will used to call ExtractConfig.
- //
- if (!ConfigRequestAdjust(Storage, &ConfigRequest)) {
- return EFI_SUCCESS;
- }
+ //
+ // 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);
- //
- // Request current settings from Configuration Driver
- //
- Status = FormSet->ConfigAccess->ExtractConfig (
- FormSet->ConfigAccess,
- ConfigRequest,
- &Progress,
- &Result
- );
- FreePool (ConfigRequest);
+ 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 <ConfigAltResp> to <ConfigResp>
+ //
+ StrPtr = StrStr (Result, L"&GUID=");
+ if (StrPtr != NULL) {
+ *StrPtr = L'\0';
+ }
+
+ Status = ConfigRespToStorage (Storage->BrowserStorage, Result);
+ FreePool (Result);
+ }
+ }
- if (EFI_ERROR (Status)) {
- return Status;
- }
+ if (EFI_ERROR (Status)) {
+ //
+ // Base on the configRequest string to get default value.
+ //
+ GetDefaultForFormset (FormSet, Storage->BrowserStorage, Storage->ConfigElements);
+ }
- //
- // Convert Result from <ConfigAltResp> to <ConfigResp>
- //
- StrPtr = StrStr (Result, L"&GUID=");
- if (StrPtr != NULL) {
- *StrPtr = L'\0';
- }
+ SynchronizeStorage(FormSet, Storage->BrowserStorage, Storage->ConfigElements, TRUE);
+ break;
- Status = ConfigRespToStorage (Storage->BrowserStorage, Result);
- FreePool (Result);
- return Status;
+ default:
+ break;
+ }
}
/**
@@ -3827,22 +4314,15 @@ LoadStorage (
@param FormSet FormSet data structure.
- @retval EFI_SUCCESS The function completed successfully.
-
**/
-EFI_STATUS
+VOID
InitializeCurrentSetting (
IN OUT FORM_BROWSER_FORMSET *FormSet
)
{
LIST_ENTRY *Link;
- LIST_ENTRY *Link2;
FORMSET_STORAGE *Storage;
- FORMSET_STORAGE *StorageSrc;
- FORMSET_STORAGE *OldStorage;
- FORM_BROWSER_FORM *Form;
- FORM_BROWSER_FORM *Form2;
- EFI_STATUS Status;
+ FORM_BROWSER_FORMSET *OldFormSet;
//
// Extract default from IFR binary for no storage questions.
@@ -3856,77 +4336,21 @@ InitializeCurrentSetting (
while (!IsNull (&FormSet->StorageListHead, Link)) {
Storage = FORMSET_STORAGE_FROM_LINK (Link);
- 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);
- }
+ LoadStorage (FormSet, Storage);
Link = GetNextNode (&FormSet->StorageListHead, Link);
}
//
- // If has old formset, get the old nv update status.
+ // Try to find pre FormSet in the maintain backup list.
+ // If old formset != NULL, destroy this formset. Add new formset to gBrowserFormSetList.
//
- 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);
- }
+ OldFormSet = GetFormSetFromHiiHandle (FormSet->HiiHandle);
+ if (OldFormSet != NULL) {
+ RemoveEntryList (&OldFormSet->Link);
+ DestroyFormSet (OldFormSet);
}
-
- return EFI_SUCCESS;
+ InsertTailList (&gBrowserFormSetList, &FormSet->Link);
}
@@ -4109,7 +4533,6 @@ 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.
@@ -4119,13 +4542,11 @@ EFI_STATUS
InitializeFormSet (
IN EFI_HII_HANDLE Handle,
IN OUT EFI_GUID *FormSetGuid,
- OUT FORM_BROWSER_FORMSET *FormSet,
- IN BOOLEAN UpdateGlobalVar
+ OUT FORM_BROWSER_FORMSET *FormSet
)
{
EFI_STATUS Status;
EFI_HANDLE DriverHandle;
- UINT16 Index;
Status = GetIfrBinaryData (Handle, FormSetGuid, &FormSet->IfrBinaryLength, &FormSet->IfrBinaryData);
if (EFI_ERROR (Status)) {
@@ -4135,6 +4556,7 @@ 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
@@ -4161,53 +4583,8 @@ InitializeFormSet (
// Parse the IFR binary OpCodes
//
Status = ParseOpCodes (FormSet);
- if (EFI_ERROR (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;
- }
- }
-
- 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;
+ return Status;
}
@@ -4223,6 +4600,7 @@ SaveBrowserContext (
)
{
BROWSER_CONTEXT *Context;
+ FORM_ENTRY_INFO *MenuList;
gBrowserContextCount++;
if (gBrowserContextCount == 1) {
@@ -4240,47 +4618,23 @@ SaveBrowserContext (
//
// Save FormBrowser context
//
- Context->BannerData = gBannerData;
- Context->ClassOfVfr = gClassOfVfr;
- Context->FunctionKeySetting = gFunctionKeySetting;
+ Context->Selection = gCurrentSelection;
Context->ResetRequired = gResetRequired;
- 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));
+ 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);
+ }
//
// Insert to FormBrowser context list
@@ -4300,6 +4654,7 @@ RestoreBrowserContext (
{
LIST_ENTRY *Link;
BROWSER_CONTEXT *Context;
+ FORM_ENTRY_INFO *MenuList;
ASSERT (gBrowserContextCount != 0);
gBrowserContextCount--;
@@ -4318,47 +4673,22 @@ RestoreBrowserContext (
//
// Restore FormBrowser context
//
- gBannerData = Context->BannerData;
- gClassOfVfr = Context->ClassOfVfr;
- gFunctionKeySetting = Context->FunctionKeySetting;
+ gCurrentSelection = Context->Selection;
gResetRequired = Context->ResetRequired;
- 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));
+ 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);
+ }
//
// Remove from FormBrowser context list
@@ -4418,7 +4748,7 @@ IsHiiHandleInBrowserContext (
//
// HiiHandle is Current FormSet.
//
- if ((gOldFormSet != NULL) && (gOldFormSet->HiiHandle == Handle)) {
+ if (mCurrentHiiHandle == Handle) {
return TRUE;
}
@@ -4428,7 +4758,7 @@ IsHiiHandleInBrowserContext (
Link = GetFirstNode (&gBrowserContextList);
while (!IsNull (&gBrowserContextList, Link)) {
Context = BROWSER_CONTEXT_FROM_LINK (Link);
- if (Context->OldFormSet->HiiHandle == Handle) {
+ if (Context->HiiHandle == Handle) {
//
// HiiHandle is in BrowserContext
//
@@ -4441,6 +4771,83 @@ IsHiiHandleInBrowserContext (
}
/**
+ 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.
@param[in] KeyData A pointer to a buffer that describes the keystroke
@@ -4490,7 +4897,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.
@@ -4615,6 +5022,128 @@ RegiserExitHandler (
}
/**
+ 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.
@@ -4633,12 +5162,6 @@ 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;
@@ -4649,7 +5172,7 @@ SaveReminder (
if (!ValidateFormSet(FormSet)) {
continue;
}
- if (IsNvUpdateRequired (FormSet)) {
+ if (IsNvUpdateRequiredForFormSet (FormSet)) {
IsDataChanged = TRUE;
break;
}
@@ -4663,42 +5186,19 @@ SaveReminder (
}
//
- // If data is changed, prompt user
+ // If data is changed, prompt user to save or discard it.
//
- 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 {
- 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))
- );
+ DataSavedAction = (UINT32) mFormDisplay->ConfirmDataChange();
- //
- // 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);
+ if (DataSavedAction == BROWSER_SAVE_CHANGES) {
+ SubmitForm (NULL, NULL, SystemLevel);
+ break;
+ } else if (DataSavedAction == BROWSER_DISCARD_CHANGES) {
+ DiscardForm (NULL, NULL, SystemLevel);
+ break;
+ }
+ } while (1);
return DataSavedAction;
}
diff --git a/MdeModulePkg/Universal/SetupBrowserDxe/Setup.h b/MdeModulePkg/Universal/SetupBrowserDxe/Setup.h
index 9a0c739..030cf32 100644
--- a/MdeModulePkg/Universal/SetupBrowserDxe/Setup.h
+++ b/MdeModulePkg/Universal/SetupBrowserDxe/Setup.h
@@ -22,7 +22,8 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
#include <Protocol/SimpleTextOut.h>
#include <Protocol/SimpleTextIn.h>
#include <Protocol/FormBrowser2.h>
-#include <Protocol/FormBrowserEx.h>
+#include <Protocol/FormBrowserEx2.h>
+#include <Protocol/DisplayProtocol.h>
#include <Protocol/DevicePath.h>
#include <Protocol/UnicodeCollation.h>
#include <Protocol/HiiConfigAccess.h>
@@ -47,106 +48,29 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
#include <Library/HiiLib.h>
#include <Library/PcdLib.h>
#include <Library/DevicePathLib.h>
+#include <Library/UefiLib.h>
-#include "Colors.h"
//
// This is the generated header file which includes whatever needs to be exported (strings + IFR)
//
-extern UINT8 SetupBrowserStrings[];
+#define UI_ACTION_NONE 0
+#define UI_ACTION_REFRESH_FORM 1
+#define UI_ACTION_REFRESH_FORMSET 2
+#define UI_ACTION_EXIT 3
//
-// 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
//
#define EXPRESSION_STACK_SIZE_INCREMENT 0x100
@@ -163,15 +87,12 @@ typedef struct {
//
// Produced protocol
//
- EFI_FORM_BROWSER2_PROTOCOL FormBrowser2;
-
- EFI_FORM_BROWSER_EXTENSION_PROTOCOL FormBrowserEx;
+ EFI_FORM_BROWSER2_PROTOCOL FormBrowser2;
+ EFI_FORM_BROWSER_EXTENSION_PROTOCOL FormBrowserEx;
-} SETUP_DRIVER_PRIVATE_DATA;
+ EDKII_FORM_BROWSER_EXTENSION2_PROTOCOL FormBrowserEx2;
-typedef struct {
- EFI_STRING_ID Banner[BANNER_HEIGHT][BANNER_COLUMNS];
-} BANNER_DATA;
+} SETUP_DRIVER_PRIVATE_DATA;
//
// IFR relative definition
@@ -194,16 +115,6 @@ 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 {
@@ -255,6 +166,7 @@ typedef struct {
BROWSER_STORAGE *BrowserStorage;
CHAR16 *ConfigRequest; // <ConfigRequest> = <ConfigHdr> + <RequestElement>
+ CHAR16 *ConfigElements;// Elements need to load initial data.
UINTN ElementCount; // Number of <RequestElement> in the <ConfigRequest>
UINTN SpareStrLen; // Spare length of ConfigRequest string buffer
} FORMSET_STORAGE;
@@ -344,6 +256,8 @@ typedef struct {
typedef struct {
UINTN Signature;
LIST_ENTRY Link;
+
+ EFI_IFR_ONE_OF_OPTION *OpCode; // OneOfOption Data
EFI_STRING_ID Text;
UINT8 Flags;
@@ -376,6 +290,7 @@ typedef struct {
LIST_ENTRY Link;
UINT8 Operand; // The operand (first byte) of this Statement or Question
+ EFI_IFR_OP_HEADER *OpCode;
//
// Statement Header
@@ -385,6 +300,11 @@ typedef struct {
EFI_STRING_ID TextTwo; // For EFI_IFR_TEXT
//
+ // Fake Question Id, used for statement not has true QuestionId.
+ //
+ EFI_QUESTION_ID FakeQuestionId;
+
+ //
// Question Header
//
EFI_QUESTION_ID QuestionId; // The value of zero is reserved
@@ -417,6 +337,7 @@ 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
//
@@ -467,8 +388,6 @@ 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.
@@ -502,6 +421,7 @@ typedef struct {
UINTN IfrBinaryLength;
UINT8 *IfrBinaryData;
+ BOOLEAN QuestionInited; // Have finished question initilization?
EFI_GUID Guid;
EFI_STRING_ID FormSetTitle;
EFI_STRING_ID Help;
@@ -514,84 +434,82 @@ 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)
-#define BROWSER_CONTEXT_SIGNATURE SIGNATURE_32 ('B', 'C', 'T', 'X')
+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)
+
typedef struct {
- UINTN Signature;
- LIST_ENTRY Link;
+ EFI_HII_HANDLE Handle;
//
- // Globals defined in Setup.c
+ // Target formset/form/Question information
//
- 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;
+ EFI_GUID FormSetGuid;
+ UINT16 FormId;
+ UINT16 QuestionId;
+ UINTN Sequence; // used for time/date only.
+
+ UINTN TopRow;
+ UINTN BottomRow;
+ UINTN PromptCol;
+ UINTN OptionCol;
+ UINTN CurrentRow;
//
- // Globals defined in Ui.c
+ // 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
//
- LIST_ENTRY MenuOption;
- VOID *MenuRefreshHead;
-} BROWSER_CONTEXT;
+ UINTN Action;
-#define BROWSER_CONTEXT_FROM_LINK(a) CR (a, BROWSER_CONTEXT, Link, BROWSER_CONTEXT_SIGNATURE)
+ //
+ // Current selected fomset/form/Question
+ //
+ FORM_BROWSER_FORMSET *FormSet;
+ FORM_BROWSER_FORM *Form;
+ FORM_BROWSER_STATEMENT *Statement;
-#define BROWSER_HOT_KEY_SIGNATURE SIGNATURE_32 ('B', 'H', 'K', 'S')
+ //
+ // Whether the Form is editable
+ //
+ BOOLEAN FormEditable;
+
+ FORM_ENTRY_INFO *CurrentMenu;
+} UI_MENU_SELECTION;
+
+#define BROWSER_CONTEXT_SIGNATURE SIGNATURE_32 ('B', 'C', 'T', 'X')
typedef struct {
UINTN Signature;
LIST_ENTRY Link;
-
- EFI_INPUT_KEY *KeyData;
- IN UINT32 Action;
- IN UINT16 DefaultId;
- IN EFI_STRING HelpString;
-} BROWSER_HOT_KEY;
-#define BROWSER_HOT_KEY_FROM_LINK(a) CR (a, BROWSER_HOT_KEY, Link, BROWSER_HOT_KEY_SIGNATURE)
+ //
+ // 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)
//
// Scope for get defaut value. It may be GetDefaultForNoStorage, GetDefaultForStorage or GetDefaultForAll.
@@ -614,72 +532,31 @@ 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 EFI_HII_HANDLE gHiiHandle;
-extern UINT16 gDirection;
-extern EFI_SCREEN_DESCRIPTOR gScreenDimensions;
+extern BOOLEAN gExitRequired;
-extern FORM_BROWSER_FORMSET *gOldFormSet;
extern LIST_ENTRY gBrowserFormSetList;
extern LIST_ENTRY gBrowserHotKeyList;
extern BROWSER_SETTING_SCOPE gBrowserSettingScope;
extern EXIT_HANDLER ExitHandlerFunction;
-extern UINTN gFooterHeight;
-
+extern EFI_HII_HANDLE mCurrentHiiHandle;
//
// 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;
-#include "Ui.h"
+extern UI_MENU_SELECTION *gCurrentSelection;
+
//
// Global Procedure Defines
//
+#include "Expression.h"
/**
Initialize the HII String Token to the correct values.
@@ -691,91 +568,6 @@ InitializeBrowserStrings (
);
/**
- 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.
@param FormSet Pointer of the FormSet data structure.
@@ -800,17 +592,6 @@ 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.
@@ -860,59 +641,6 @@ GetToken (
);
/**
- 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.
@param Storage The NameValue Storage.
@@ -939,6 +667,7 @@ 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.
@@ -946,10 +675,31 @@ GetValueByName (
**/
EFI_STATUS
SetValueByName (
- IN BROWSER_STORAGE *Storage,
- IN CHAR16 *Name,
- IN CHAR16 *Value,
- IN GET_SET_QUESTION_VALUE_WITH SetValueTo
+ 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
);
/**
@@ -1071,10 +821,8 @@ GetQuestionDefault (
@param FormSet FormSet data structure.
- @retval EFI_SUCCESS The function completed successfully.
-
**/
-EFI_STATUS
+VOID
InitializeCurrentSetting (
IN OUT FORM_BROWSER_FORMSET *FormSet
);
@@ -1087,7 +835,6 @@ 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.
@@ -1097,8 +844,7 @@ EFI_STATUS
InitializeFormSet (
IN EFI_HII_HANDLE Handle,
IN OUT EFI_GUID *FormSetGuid,
- OUT FORM_BROWSER_FORMSET *FormSet,
- IN BOOLEAN UpdateGlobalVar
+ OUT FORM_BROWSER_FORMSET *FormSet
);
/**
@@ -1176,6 +922,7 @@ LoadFormSetConfig (
@param Storage The Storage to be conveted.
@param ConfigResp The returned <ConfigResp>.
@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.
@@ -1185,7 +932,8 @@ EFI_STATUS
StorageToConfigResp (
IN BROWSER_STORAGE *Storage,
IN CHAR16 **ConfigResp,
- IN CHAR16 *ConfigRequest
+ IN CHAR16 *ConfigRequest,
+ IN BOOLEAN GetEditBuf
);
/**
@@ -1210,10 +958,8 @@ ConfigRespToStorage (
@param FormSet FormSet data structure.
@param Storage Buffer Storage.
- @retval EFI_SUCCESS The function completed successfully.
-
**/
-EFI_STATUS
+VOID
LoadStorage (
IN FORM_BROWSER_FORMSET *FormSet,
IN FORMSET_STORAGE *Storage
@@ -1349,30 +1095,29 @@ BrowserCallback (
about the Selection, form and formset to be displayed.
On output, Selection return the screen item that is selected
by user.
- @param Repaint Whether need to repaint the menu.
- @param NewLine Whether need to show at new line.
+ @param SettingLevel Input Settting level, if it is FormLevel, just exit current form.
+ else, we need to exit current formset.
- @retval TRUE Need return.
- @retval FALSE No need to return.
+ @retval TRUE Exit current form.
+ @retval FALSE User press ESC and keep in current form.
**/
BOOLEAN
FindNextMenu (
- IN OUT UI_MENU_SELECTION *Selection,
- IN BOOLEAN *Repaint,
- IN BOOLEAN *NewLine
+ IN OUT UI_MENU_SELECTION *Selection,
+ IN BROWSER_SETTING_SCOPE SettingLevel
);
/**
- check whether the formset need to update the NV.
+ check whether the form need to update the NV.
- @param FormSet FormSet data structure.
- @param SetValue Whether set new value or clear old value.
+ @param Form Form data structure.
+ @retval TRUE Need to update the NV.
+ @retval FALSE No need to update the NV.
**/
-VOID
-UpdateNvInfoInForm (
- IN FORM_BROWSER_FORMSET *FormSet,
- IN BOOLEAN SetValue
+BOOLEAN
+IsNvUpdateRequiredForForm (
+ IN FORM_BROWSER_FORM *Form
);
/**
@@ -1383,12 +1128,25 @@ UpdateNvInfoInForm (
@retval TRUE Need to update the NV.
@retval FALSE No need to update the NV.
**/
-BOOLEAN
-IsNvUpdateRequired (
+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
+ );
+
+/**
Call the call back function for the question and process the return action.
@param Selection On input, Selection tell setup browser the information
@@ -1517,6 +1275,38 @@ RegiserExitHandler (
);
/**
+
+ 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.
@@ -1545,6 +1335,267 @@ GetHotKeyFromRegisterList (
);
/**
+
+ 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.
@param FormSet Pointer of the FormSet
@@ -1554,5 +1605,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 2a4cda4..a3f3a6f 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 = 1.0
+ VERSION_STRING = 2.0
ENTRY_POINT = InitializeSetup
#
@@ -29,19 +29,12 @@
#
[Sources]
- SetupBrowserStr.uni
Setup.c
Setup.h
IfrParse.c
Expression.c
- InputHandler.c
- Print.c
Presentation.c
- ProcessOptions.c
- Ui.c
- Ui.h
- Colors.h
-
+ Expression.h
[Packages]
MdePkg/MdePkg.dec
@@ -59,33 +52,27 @@
HiiLib
DevicePathLib
PcdLib
+ UefiLib
[Guids]
- gEfiIfrTianoGuid ## CONSUMES ## GUID
gEfiIfrFrameworkGuid ## CONSUMES ## GUID
gEfiHiiPlatformSetupFormsetGuid
gEfiHiiStandardFormGuid ## SOMETIMES_CONSUMES ## GUID
[Protocols]
gEfiHiiConfigAccessProtocolGuid ## CONSUMES
- gEfiHiiStringProtocolGuid ## CONSUMES
gEfiFormBrowser2ProtocolGuid ## PRODUCES
- gEfiFormBrowserExProtocolGuid ## PRODUCES
+ gEdkiiFormBrowserEx2ProtocolGuid ## PRODUCES
gEfiHiiConfigRoutingProtocolGuid ## CONSUMES
gEfiHiiDatabaseProtocolGuid ## CONSUMES
gEfiUnicodeCollation2ProtocolGuid ## CONSUMES
gEfiUserManagerProtocolGuid ## SOMETIMES_CONSUMES
gEfiDevicePathFromTextProtocolGuid ## SOMETIMES_CONSUMES
+ gEdkiiFormDisplayEngineProtocolGuid ## PRODUCE
+ gEfiFormBrowserExProtocolGuid ## PRODUCE
[FeaturePcd]
gEfiMdeModulePkgTokenSpaceGuid.PcdFrameworkCompatibilitySupport ## CONSUMES
- gEfiMdeModulePkgTokenSpaceGuid.PcdBrowserGrayOutTextStatement ## CONSUMES
-
-[Pcd]
- gEfiMdeModulePkgTokenSpaceGuid.PcdBrowserSubtitleTextColor ## CONSUMES
- gEfiMdeModulePkgTokenSpaceGuid.PcdBrowserFieldTextColor ## CONSUMES
- gEfiMdeModulePkgTokenSpaceGuid.PcdBrowserFieldTextHighlightColor ## CONSUMES
- gEfiMdeModulePkgTokenSpaceGuid.PcdBrowserFieldBackgroundHighlightColor ## CONSUMES
[Depex]
gEfiHiiDatabaseProtocolGuid AND gEfiHiiConfigRoutingProtocolGuid
diff --git a/MdeModulePkg/Universal/SetupBrowserDxe/Ui.c b/MdeModulePkg/Universal/SetupBrowserDxe/Ui.c
deleted file mode 100644
index 1688d54..0000000
--- a/MdeModulePkg/Universal/SetupBrowserDxe/Ui.c
+++ /dev/null
@@ -1,4011 +0,0 @@
-/** @file
-Utility functions for User Interface functions.
-
-Copyright (c) 2004 - 2013, Intel Corporation. All rights reserved.<BR>
-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 = INITIALIZE_LIST_HEAD_VARIABLE (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 and FormSetGuid in all cached menu list.
-
- @param Parent The parent of menu to search.
- @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_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)) {
- return Parent;
- }
-
- Link = GetFirstNode (&Parent->ChildListHead);
- while (!IsNull (&Parent->ChildListHead, Link)) {
- Child = UI_MENU_LIST_FROM_LINK (Link);
-
- MenuList = UiFindChildMenuList (Child, FormSetGuid, FormId);
- if (MenuList != NULL) {
- return MenuList;
- }
-
- Link = GetNextNode (&Parent->ChildListHead, Link);
- }
-
- return NULL;
-}
-
-
-/**
- Search Menu with given FormSetGuid and FormId in all cached menu list.
-
- @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_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, FormSetGuid, FormId);
- if (Child != NULL) {
- return Child;
- }
-
- Link = GetNextNode (&gMenuList, Link);
- }
-
- return NULL;
-}
-
-
-/**
- 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;
- }
-
- 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;
- UINTN StringLen;
- EFI_DEVICE_PATH_PROTOCOL *DevicePath;
- FORM_BROWSER_FORM *RefForm;
- EFI_INPUT_KEY Key;
- EFI_STATUS Status;
- UI_MENU_LIST *MenuList;
- BOOLEAN UpdateFormInfo;
-
- Status = EFI_SUCCESS;
- UpdateFormInfo = TRUE;
- StringPtr = NULL;
- StringLen = 0;
-
- //
- // 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);
- if (StringPtr != NULL) {
- StringLen = StrLen (StringPtr);
- }
- }
-
- //
- // Check whether the device path string is a valid string.
- //
- if (Statement->HiiValue.Value.ref.DevicePath != 0 && StringPtr != NULL && StringLen != 0) {
- 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;
- }
- }
- UpdateFormInfo = FALSE;
- } else {
- if ((Statement->QuestionFlags & EFI_IFR_FLAG_CALLBACK) != 0) {
- Selection->Action = UI_ACTION_REFRESH_FORM;
- }
- UpdateFormInfo = FALSE;
- }
-
- if (UpdateFormInfo) {
- //
- // Link current form so that we can always go back when someone hits the ESC
- //
- MenuList = UiFindMenuList (&Selection->FormSetGuid, Selection->FormId);
- if (MenuList == NULL && Selection->CurrentMenu != NULL) {
- MenuList = UiAddMenuList (Selection->CurrentMenu, Selection->Handle, &Selection->FormSetGuid, Selection->FormId);
- }
- }
-
- 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->FormSetGuid, Selection->FormId);
- if (CurrentMenu == NULL) {
- //
- // Current menu not found, add it to the menu tree
- //
- CurrentMenu = UiAddMenuList (NULL, 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) || (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 <ConfigResp>
- //
- 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
deleted file mode 100644
index dc4facf..0000000
--- a/MdeModulePkg/Universal/SetupBrowserDxe/Ui.h
+++ /dev/null
@@ -1,1031 +0,0 @@
-/** @file
-Private structure, MACRO and function definitions for User Interface related functionalities.
-
-Copyright (c) 2004 - 2013, Intel Corporation. All rights reserved.<BR>
-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 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 in the parent menu and all its child menus.
-
- @param Parent The parent of menu to search.
- @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_GUID *FormSetGuid,
- IN UINT16 FormId
- );
-
-/**
- Search Menu with given FormSetGuid and FormId in all cached menu list.
-
- @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_GUID *FormSetGuid,
- IN UINT16 FormId
- );
-
-/**
- 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
- );
-
-/**
- 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