2019-09-03 11:58:42 +02:00
/** @file
Entry and initialization module for the browser .
Copyright ( c ) 2007 - 2018 , Intel Corporation . All rights reserved . < BR >
Copyright ( c ) 2014 , Hewlett - Packard Development Company , L . P . < BR >
SPDX - License - Identifier : BSD - 2 - Clause - Patent
* */
# 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 = ARRAY_SIZE ( gScanCodeToOperation ) ;
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 }
} ;
BOOLEAN gMisMatch ;
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 * gReconnectConfirmChanges ;
CHAR16 * gReconnectFail ;
CHAR16 * gReconnectRequired ;
CHAR16 * gChangesOpt ;
CHAR16 * gFormNotFound ;
CHAR16 * gNoSubmitIf ;
CHAR16 * gBrowserError ;
CHAR16 * gSaveFailed ;
CHAR16 * gNoSubmitIfFailed ;
CHAR16 * gSaveProcess ;
CHAR16 * gSaveNoSubmitProcess ;
CHAR16 * gDiscardChange ;
CHAR16 * gJumpToFormSet ;
CHAR16 * gCheckError ;
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 * gConfirmDefaultMsg ;
CHAR16 * gConfirmSubmitMsg ;
CHAR16 * gConfirmDiscardMsg ;
CHAR16 * gConfirmResetMsg ;
CHAR16 * gConfirmExitMsg ;
CHAR16 * gConfirmSubmitMsg2nd ;
CHAR16 * gConfirmDefaultMsg2nd ;
CHAR16 * gConfirmResetMsg2nd ;
CHAR16 * gConfirmExitMsg2nd ;
CHAR16 * gConfirmOpt ;
CHAR16 * gConfirmOptYes ;
CHAR16 * gConfirmOptNo ;
CHAR16 * gConfirmOptOk ;
CHAR16 * gConfirmOptCancel ;
CHAR16 * gYesOption ;
CHAR16 * gNoOption ;
CHAR16 * gOkOption ;
CHAR16 * gCancelOption ;
CHAR16 * gErrorPopup ;
CHAR16 * gWarningPopup ;
CHAR16 * gInfoPopup ;
CHAR16 * gConfirmMsgConnect ;
CHAR16 * gConfirmMsgEnd ;
CHAR16 * gPasswordUnsupported ;
CHAR16 gModalSkipColumn ;
CHAR16 gPromptBlockWidth ;
CHAR16 gOptionBlockWidth ;
CHAR16 gHelpBlockWidth ;
CHAR16 * mUnknownString ;
FORM_DISPLAY_DRIVER_PRIVATE_DATA mPrivateData = {
FORM_DISPLAY_DRIVER_SIGNATURE ,
NULL ,
{
FormDisplay ,
DriverClearDisplayPage ,
ConfirmDataChange
} ,
{
EFI_HII_POPUP_PROTOCOL_REVISION ,
CreatePopup
}
} ;
/**
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 ) {
2020-04-27 17:16:43 +02:00
String = AllocateCopyPool ( StrSize ( mUnknownString ) , mUnknownString ) ;
2019-09-03 11:58:42 +02:00
ASSERT ( String ! = NULL ) ;
}
return ( CHAR16 * ) String ;
}
/**
Initialize the HII String Token to the correct values .
* */
VOID
InitializeDisplayStrings (
VOID
)
{
gReconnectConfirmChanges = GetToken ( STRING_TOKEN ( RECONNECT_CONFIRM_CHANGES ) , gHiiHandle ) ;
mUnknownString = GetToken ( STRING_TOKEN ( UNKNOWN_STRING ) , gHiiHandle ) ;
gSaveFailed = GetToken ( STRING_TOKEN ( SAVE_FAILED ) , gHiiHandle ) ;
gNoSubmitIfFailed = GetToken ( STRING_TOKEN ( NO_SUBMIT_IF_CHECK_FAILED ) , gHiiHandle ) ;
gReconnectFail = GetToken ( STRING_TOKEN ( RECONNECT_FAILED ) , gHiiHandle ) ;
gReconnectRequired = GetToken ( STRING_TOKEN ( RECONNECT_REQUIRED ) , gHiiHandle ) ;
gChangesOpt = GetToken ( STRING_TOKEN ( RECONNECT_CHANGES_OPTIONS ) , gHiiHandle ) ;
gSaveProcess = GetToken ( STRING_TOKEN ( DISCARD_OR_JUMP ) , gHiiHandle ) ;
gSaveNoSubmitProcess = GetToken ( STRING_TOKEN ( DISCARD_OR_CHECK ) , gHiiHandle ) ;
gDiscardChange = GetToken ( STRING_TOKEN ( DISCARD_OR_JUMP_DISCARD ) , gHiiHandle ) ;
gJumpToFormSet = GetToken ( STRING_TOKEN ( DISCARD_OR_JUMP_JUMP ) , gHiiHandle ) ;
gCheckError = GetToken ( STRING_TOKEN ( DISCARD_OR_CHECK_CHECK ) , 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 ) ;
gBrowserError = GetToken ( STRING_TOKEN ( STATUS_BROWSER_ERROR ) , gHiiHandle ) ;
gConfirmDefaultMsg = GetToken ( STRING_TOKEN ( CONFIRM_DEFAULT_MESSAGE ) , gHiiHandle ) ;
gConfirmDiscardMsg = GetToken ( STRING_TOKEN ( CONFIRM_DISCARD_MESSAGE ) , gHiiHandle ) ;
gConfirmSubmitMsg = GetToken ( STRING_TOKEN ( CONFIRM_SUBMIT_MESSAGE ) , gHiiHandle ) ;
gConfirmResetMsg = GetToken ( STRING_TOKEN ( CONFIRM_RESET_MESSAGE ) , gHiiHandle ) ;
gConfirmExitMsg = GetToken ( STRING_TOKEN ( CONFIRM_EXIT_MESSAGE ) , gHiiHandle ) ;
gConfirmDefaultMsg2nd = GetToken ( STRING_TOKEN ( CONFIRM_DEFAULT_MESSAGE_2ND ) , gHiiHandle ) ;
gConfirmSubmitMsg2nd = GetToken ( STRING_TOKEN ( CONFIRM_SUBMIT_MESSAGE_2ND ) , gHiiHandle ) ;
gConfirmResetMsg2nd = GetToken ( STRING_TOKEN ( CONFIRM_RESET_MESSAGE_2ND ) , gHiiHandle ) ;
gConfirmExitMsg2nd = GetToken ( STRING_TOKEN ( CONFIRM_EXIT_MESSAGE_2ND ) , gHiiHandle ) ;
gConfirmOpt = GetToken ( STRING_TOKEN ( CONFIRM_OPTION ) , gHiiHandle ) ;
gConfirmOptYes = GetToken ( STRING_TOKEN ( CONFIRM_OPTION_YES ) , gHiiHandle ) ;
gConfirmOptNo = GetToken ( STRING_TOKEN ( CONFIRM_OPTION_NO ) , gHiiHandle ) ;
gConfirmOptOk = GetToken ( STRING_TOKEN ( CONFIRM_OPTION_OK ) , gHiiHandle ) ;
gConfirmOptCancel = GetToken ( STRING_TOKEN ( CONFIRM_OPTION_CANCEL ) , gHiiHandle ) ;
gYesOption = GetToken ( STRING_TOKEN ( YES_SELECTABLE_OPTION ) , gHiiHandle ) ;
gNoOption = GetToken ( STRING_TOKEN ( NO_SELECTABLE_OPTION ) , gHiiHandle ) ;
gOkOption = GetToken ( STRING_TOKEN ( OK_SELECTABLE_OPTION ) , gHiiHandle ) ;
gCancelOption = GetToken ( STRING_TOKEN ( CANCEL_SELECTABLE_OPTION ) , gHiiHandle ) ;
gErrorPopup = GetToken ( STRING_TOKEN ( ERROR_POPUP_STRING ) , gHiiHandle ) ;
gWarningPopup = GetToken ( STRING_TOKEN ( WARNING_POPUP_STRING ) , gHiiHandle ) ;
gInfoPopup = GetToken ( STRING_TOKEN ( INFO_POPUP_STRING ) , gHiiHandle ) ;
gConfirmMsgConnect = GetToken ( STRING_TOKEN ( CONFIRM_OPTION_CONNECT ) , gHiiHandle ) ;
gConfirmMsgEnd = GetToken ( STRING_TOKEN ( CONFIRM_OPTION_END ) , gHiiHandle ) ;
gPasswordUnsupported = GetToken ( STRING_TOKEN ( PASSWORD_NOT_SUPPORTED ) , gHiiHandle ) ;
}
/**
Free up the resource allocated for all strings required
by Setup Browser .
* */
VOID
FreeDisplayStrings (
VOID
)
{
2020-04-23 11:08:10 +02:00
FreePool ( mUnknownString ) ;
FreePool ( gEmptyString ) ;
FreePool ( gSaveFailed ) ;
FreePool ( gNoSubmitIfFailed ) ;
FreePool ( gReconnectFail ) ;
FreePool ( gReconnectRequired ) ;
FreePool ( gChangesOpt ) ;
FreePool ( gReconnectConfirmChanges ) ;
FreePool ( gSaveProcess ) ;
FreePool ( gSaveNoSubmitProcess ) ;
FreePool ( gDiscardChange ) ;
FreePool ( gJumpToFormSet ) ;
FreePool ( gCheckError ) ;
FreePool ( gPromptForData ) ;
FreePool ( gPromptForPassword ) ;
FreePool ( gPromptForNewPassword ) ;
FreePool ( gConfirmPassword ) ;
FreePool ( gConfirmError ) ;
FreePool ( gPassowordInvalid ) ;
FreePool ( gPressEnter ) ;
FreePool ( gMiniString ) ;
FreePool ( gOptionMismatch ) ;
FreePool ( gFormSuppress ) ;
FreePool ( gProtocolNotFound ) ;
FreePool ( gBrowserError ) ;
FreePool ( gNoSubmitIf ) ;
FreePool ( gFormNotFound ) ;
FreePool ( gConfirmDefaultMsg ) ;
FreePool ( gConfirmSubmitMsg ) ;
FreePool ( gConfirmDiscardMsg ) ;
FreePool ( gConfirmResetMsg ) ;
FreePool ( gConfirmExitMsg ) ;
FreePool ( gConfirmDefaultMsg2nd ) ;
FreePool ( gConfirmSubmitMsg2nd ) ;
FreePool ( gConfirmResetMsg2nd ) ;
FreePool ( gConfirmExitMsg2nd ) ;
FreePool ( gConfirmOpt ) ;
FreePool ( gConfirmOptYes ) ;
FreePool ( gConfirmOptNo ) ;
FreePool ( gConfirmOptOk ) ;
FreePool ( gConfirmOptCancel ) ;
FreePool ( gYesOption ) ;
FreePool ( gNoOption ) ;
FreePool ( gOkOption ) ;
FreePool ( gCancelOption ) ;
FreePool ( gErrorPopup ) ;
FreePool ( gWarningPopup ) ;
FreePool ( gInfoPopup ) ;
FreePool ( gConfirmMsgConnect ) ;
FreePool ( gConfirmMsgEnd ) ;
FreePool ( gPasswordUnsupported ) ;
2019-09-03 11:58:42 +02:00
}
/**
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 MenuOption The menu option .
@ param AdjustWidth The width which is saved for the space .
@ return Returns the number of CHAR16 characters that is support .
* */
UINT16
GetWidth (
IN UI_MENU_OPTION * MenuOption ,
OUT UINT16 * AdjustWidth
)
{
CHAR16 * String ;
UINTN Size ;
EFI_IFR_TEXT * TestOp ;
UINT16 ReturnWidth ;
FORM_DISPLAY_ENGINE_STATEMENT * Statement ;
Statement = MenuOption - > ThisTag ;
//
// For modal form, clean the entire row.
//
if ( ( gFormData - > Attribute & HII_DISPLAY_MODAL ) ! = 0 ) {
if ( AdjustWidth ! = NULL ) {
* AdjustWidth = LEFT_SKIPPED_COLUMNS ;
}
return ( UINT16 ) ( gStatementDimensions . RightColumn - gStatementDimensions . LeftColumn - 2 * ( gModalSkipColumn + LEFT_SKIPPED_COLUMNS ) ) ;
}
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 ) ;
2020-04-23 11:08:10 +02:00
FreePool ( String ) ;
2019-09-03 11:58:42 +02:00
}
}
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 ) )
) {
//
// Return the space width.
//
if ( AdjustWidth ! = NULL ) {
* AdjustWidth = 2 ;
}
//
// Keep consistent with current behavior.
//
ReturnWidth = ( UINT16 ) ( gPromptBlockWidth + gOptionBlockWidth - 2 ) ;
} else {
if ( AdjustWidth ! = NULL ) {
* AdjustWidth = 1 ;
}
ReturnWidth = ( UINT16 ) ( gPromptBlockWidth - 1 ) ;
}
//
// For nest in statement, should the subtitle indent.
//
if ( MenuOption - > NestInStatement ) {
ReturnWidth - = SUBTITLE_INDENT ;
}
return ReturnWidth ;
}
/**
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.
//
2020-04-28 12:49:24 +02:00
* OutputString = AllocateZeroPool ( ( StrOffset + 2 ) * sizeof ( CHAR16 ) ) ;
2019-09-03 11:58:42 +02:00
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 ;
}
2020-05-01 18:26:28 +02:00
CopyMem ( ( * OutputString ) + 1 , & InputString [ * Index ] , StrOffset * sizeof ( CHAR16 ) ) ;
2019-09-03 11:58:42 +02:00
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 ;
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 ) ;
if ( Statement - > OpCode - > OpCode = = EFI_IFR_DATE_OP | | Statement - > OpCode - > OpCode = = EFI_IFR_TIME_OP ) {
Count = 3 ;
}
for ( Index = 0 ; Index < Count ; Index + + ) {
2020-04-28 12:49:24 +02:00
MenuOption = AllocateZeroPool ( sizeof ( UI_MENU_OPTION ) ) ;
2019-09-03 11:58:42 +02:00
ASSERT ( MenuOption ) ;
MenuOption - > Signature = UI_MENU_OPTION_SIGNATURE ;
MenuOption - > Description = GetToken ( PromptId , gFormData - > HiiHandle ) ;
MenuOption - > Handle = gFormData - > HiiHandle ;
MenuOption - > ThisTag = Statement ;
MenuOption - > NestInStatement = NestIn ;
MenuOption - > EntryNumber = * MenuItemCount ;
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 ;
}
}
if ( Index = = 0 & &
( Statement - > OpCode - > OpCode ! = EFI_IFR_DATE_OP ) & &
( Statement - > OpCode - > OpCode ! = EFI_IFR_TIME_OP ) ) {
Width = GetWidth ( MenuOption , NULL ) ;
for ( ; GetLineByWidth ( MenuOption - > Description , Width , & GlyphWidth , & ArrayEntry , & OutputString ) ! = 0x0000 ; ) {
//
// If there is more string to process print on the next row and increment the Skip value
//
if ( StrLen ( & MenuOption - > Description [ ArrayEntry ] ) ! = 0 ) {
NumberOfLines + + ;
}
2020-04-23 11:08:10 +02:00
FreePool ( OutputString ) ;
2019-09-03 11:58:42 +02:00
}
} else {
//
// Add three MenuOptions for Date/Time
// Data format : [01/02/2004] [11:22:33]
// Line number : 0 0 1 0 0 1
//
NumberOfLines = 0 ;
}
if ( Index = = 2 ) {
//
// Override LineNumber for the MenuOption in Date/Time sequence
//
MenuOption - > Skip = 1 ;
} else {
MenuOption - > Skip = NumberOfLines ;
}
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 ) ;
//
// Skip the opcode not recognized by Display core.
//
if ( NestStatement - > OpCode - > OpCode = = EFI_IFR_GUID_OP ) {
continue ;
}
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 - 1 ;
GlyphWidth = 1 ;
Row = 1 ;
for ( Index = 0 ; GetLineByWidth ( OptionString , Width , & GlyphWidth , & Index , & OutputString ) ! = 0x0000 ; ) {
if ( StrLen ( & OptionString [ Index ] ) ! = 0 ) {
Row + + ;
}
2020-04-23 11:08:10 +02:00
FreePool ( OutputString ) ;
2019-09-03 11:58:42 +02:00
}
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 ) ;
2020-04-23 11:08:10 +02:00
FreePool ( OptionString ) ;
2019-09-03 11:58:42 +02:00
}
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 ) ;
2020-04-23 11:08:10 +02:00
FreePool ( OptionString ) ;
2019-09-03 11:58:42 +02:00
}
}
}
/**
Check whether this Menu Option could be print .
Check Prompt string , option string or text two string not NULL .
This is an internal function .
@ param MenuOption The MenuOption to be checked .
@ retval TRUE This Menu Option is printable .
@ retval FALSE This Menu Option could not be printable .
* */
BOOLEAN
PrintableMenu (
UI_MENU_OPTION * MenuOption
)
{
EFI_STATUS Status ;
EFI_STRING OptionString ;
OptionString = NULL ;
if ( MenuOption - > Description [ 0 ] ! = ' \0 ' ) {
return TRUE ;
}
Status = ProcessOptions ( MenuOption , FALSE , & OptionString , FALSE ) ;
2020-04-23 11:08:10 +02:00
if ( EFI_ERROR ( Status ) ) {
2019-09-03 11:58:42 +02:00
return FALSE ;
}
if ( OptionString ! = NULL & & OptionString [ 0 ] ! = ' \0 ' ) {
2020-04-23 11:08:10 +02:00
FreePool ( OptionString ) ;
2019-09-03 11:58:42 +02:00
return TRUE ;
}
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 ) ;
ASSERT ( OptionString ! = NULL ) ;
if ( OptionString [ 0 ] ! = ' \0 ' ) {
2020-04-23 11:08:10 +02:00
FreePool ( OptionString ) ;
2019-09-03 11:58:42 +02:00
return TRUE ;
}
}
return FALSE ;
}
/**
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 | | ! PrintableMenu ( MenuOption ) ) {
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 .
@ param FindInForm Whether find menu in current form or beyond .
@ 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
first menu showing beyond current form or last menu showing in
current form .
The value is the line number between the new selected menu and the
current select menu , not include the new selected menu .
* */
INTN
MoveToNextStatement (
IN BOOLEAN GoUp ,
IN OUT LIST_ENTRY * * CurrentPosition ,
IN UINTN GapToTop ,
IN BOOLEAN FindInForm
)
{
INTN Distance ;
LIST_ENTRY * Pos ;
UI_MENU_OPTION * NextMenuOption ;
UI_MENU_OPTION * PreMenuOption ;
Distance = 0 ;
Pos = * CurrentPosition ;
if ( Pos = = & gMenuOption ) {
return - 1 ;
}
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 ) ;
}
//
// Check whether the menu is beyond current showing form,
// return the first one beyond the showing form.
//
if ( ( UINTN ) Distance + NextMenuOption - > Skip > GapToTop ) {
if ( FindInForm ) {
NextMenuOption = PreMenuOption ;
}
break ;
}
//
// return the selectable menu in the showing form.
//
if ( IsSelectable ( NextMenuOption ) ) {
break ;
}
Distance + = NextMenuOption - > Skip ;
//
// Arrive at begin of the menu list.
//
if ( ( GoUp ? Pos - > BackLink : Pos - > ForwardLink ) = = & gMenuOption ) {
Distance = - 1 ;
break ;
}
Pos = ( GoUp ? Pos - > BackLink : Pos - > ForwardLink ) ;
PreMenuOption = NextMenuOption ;
}
* 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 ) ;
2020-04-23 11:08:10 +02:00
ASSERT_EFI_ERROR ( Status ) ;
2019-09-03 11:58:42 +02:00
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 top of screen menu base on the current menu .
@ param CurPos Current input menu .
@ param Rows Totol screen rows .
@ param SkipValue SkipValue for this new form .
@ retval TopOfScreen Top of screen menu for the new form .
* */
LIST_ENTRY *
FindTopOfScreenMenu (
IN LIST_ENTRY * CurPos ,
IN UINTN Rows ,
OUT UINTN * SkipValue
)
{
LIST_ENTRY * Link ;
LIST_ENTRY * TopOfScreen ;
UI_MENU_OPTION * PreviousMenuOption ;
Link = CurPos ;
PreviousMenuOption = NULL ;
while ( Link - > BackLink ! = & gMenuOption ) {
Link = Link - > BackLink ;
PreviousMenuOption = MENU_OPTION_FROM_LINK ( Link ) ;
if ( PreviousMenuOption - > Row = = 0 ) {
UpdateOptionSkipLines ( PreviousMenuOption ) ;
}
if ( Rows < = PreviousMenuOption - > Skip ) {
break ;
}
Rows = Rows - PreviousMenuOption - > Skip ;
}
if ( Link - > BackLink = = & gMenuOption ) {
TopOfScreen = gMenuOption . ForwardLink ;
if ( PreviousMenuOption ! = NULL & & Rows < PreviousMenuOption - > Skip ) {
* SkipValue = PreviousMenuOption - > Skip - Rows ;
} else {
* SkipValue = 0 ;
}
} else {
TopOfScreen = Link ;
* SkipValue = PreviousMenuOption - > Skip - Rows ;
}
return TopOfScreen ;
}
/**
Get the index info for this opcode .
@ param OpCode The input opcode for the statement .
@ retval The index of this statement .
* */
UINTN
GetIndexInfoForOpcode (
IN EFI_IFR_OP_HEADER * OpCode
)
{
LIST_ENTRY * NewPos ;
UI_MENU_OPTION * MenuOption ;
UINTN Index ;
NewPos = gMenuOption . ForwardLink ;
Index = 0 ;
for ( NewPos = gMenuOption . ForwardLink ; NewPos ! = & gMenuOption ; NewPos = NewPos - > ForwardLink ) {
MenuOption = MENU_OPTION_FROM_LINK ( NewPos ) ;
if ( CompareMem ( MenuOption - > ThisTag - > OpCode , OpCode , OpCode - > Length ) = = 0 ) {
if ( MenuOption - > ThisTag - > OpCode = = OpCode ) {
return Index ;
}
Index + + ;
}
}
return Index ;
}
/**
Is this the saved highlight statement .
@ param HighLightedStatement The input highlight statement .
@ retval TRUE This is the highlight statement .
@ retval FALSE This is not the highlight statement .
* */
BOOLEAN
IsSavedHighlightStatement (
IN FORM_DISPLAY_ENGINE_STATEMENT * HighLightedStatement
)
{
if ( ( gFormData - > HiiHandle = = gHighligthMenuInfo . HiiHandle ) & &
( gFormData - > FormId = = gHighligthMenuInfo . FormId ) ) {
if ( gHighligthMenuInfo . HLTQuestionId ! = 0 ) {
return ( BOOLEAN ) ( gHighligthMenuInfo . HLTQuestionId = = GetQuestionIdInfo ( HighLightedStatement - > OpCode ) ) ;
} else {
if ( CompareMem ( gHighligthMenuInfo . HLTOpCode , HighLightedStatement - > OpCode , gHighligthMenuInfo . HLTOpCode - > Length ) = = 0 ) {
if ( gHighligthMenuInfo . HLTIndex = = 0 | | gHighligthMenuInfo . HLTIndex = = GetIndexInfoForOpcode ( HighLightedStatement - > OpCode ) ) {
return TRUE ;
} else {
return FALSE ;
}
}
}
}
return FALSE ;
}
/**
Is this the highlight menu .
@ param MenuOption The input Menu option .
@ retval TRUE This is the highlight menu option .
@ retval FALSE This is not the highlight menu option .
* */
BOOLEAN
IsHighLightMenuOption (
IN UI_MENU_OPTION * MenuOption
)
{
if ( gHighligthMenuInfo . HLTQuestionId ! = 0 ) {
if ( GetQuestionIdInfo ( MenuOption - > ThisTag - > OpCode ) = = gHighligthMenuInfo . HLTQuestionId ) {
return ( BOOLEAN ) ( MenuOption - > Sequence = = gHighligthMenuInfo . HLTSequence ) ;
}
} else {
if ( CompareMem ( gHighligthMenuInfo . HLTOpCode , MenuOption - > ThisTag - > OpCode , gHighligthMenuInfo . HLTOpCode - > Length ) = = 0 ) {
if ( gHighligthMenuInfo . HLTIndex = = 0 | | gHighligthMenuInfo . HLTIndex = = GetIndexInfoForOpcode ( MenuOption - > ThisTag - > OpCode ) ) {
return ( BOOLEAN ) ( MenuOption - > Sequence = = gHighligthMenuInfo . HLTSequence ) ;
} else {
return FALSE ;
}
}
}
return FALSE ;
}
/**
Find the highlight menu .
If the input is NULL , base on the record highlight info in
gHighligthMenuInfo to find the last highlight menu .
@ param HighLightedStatement The input highlight statement .
@ retval The highlight menu index .
* */
LIST_ENTRY *
FindHighLightMenuOption (
IN FORM_DISPLAY_ENGINE_STATEMENT * HighLightedStatement
)
{
LIST_ENTRY * NewPos ;
UI_MENU_OPTION * MenuOption ;
NewPos = gMenuOption . ForwardLink ;
MenuOption = MENU_OPTION_FROM_LINK ( NewPos ) ;
if ( HighLightedStatement ! = NULL ) {
while ( MenuOption - > ThisTag ! = HighLightedStatement ) {
NewPos = NewPos - > ForwardLink ;
if ( NewPos = = & gMenuOption ) {
//
// Not Found it, break
//
break ;
}
MenuOption = MENU_OPTION_FROM_LINK ( NewPos ) ;
}
//
// Must find the highlight statement.
//
ASSERT ( NewPos ! = & gMenuOption ) ;
} else {
while ( ! IsHighLightMenuOption ( MenuOption ) ) {
NewPos = NewPos - > ForwardLink ;
if ( NewPos = = & gMenuOption ) {
//
// Not Found it, break
//
break ;
}
MenuOption = MENU_OPTION_FROM_LINK ( NewPos ) ;
}
//
// Highlight statement has disappear (suppressed/disableed)
//
if ( NewPos = = & gMenuOption ) {
NewPos = NULL ;
}
}
return NewPos ;
}
/**
Is this the Top of screen menu .
@ param MenuOption The input Menu option .
@ retval TRUE This is the Top of screen menu option .
@ retval FALSE This is not the Top of screen menu option .
* */
BOOLEAN
IsTopOfScreeMenuOption (
IN UI_MENU_OPTION * MenuOption
)
{
if ( gHighligthMenuInfo . TOSQuestionId ! = 0 ) {
return ( BOOLEAN ) ( GetQuestionIdInfo ( MenuOption - > ThisTag - > OpCode ) = = gHighligthMenuInfo . TOSQuestionId ) ;
}
if ( CompareMem ( gHighligthMenuInfo . TOSOpCode , MenuOption - > ThisTag - > OpCode , gHighligthMenuInfo . TOSOpCode - > Length ) = = 0 ) {
if ( gHighligthMenuInfo . TOSIndex = = 0 | | gHighligthMenuInfo . TOSIndex = = GetIndexInfoForOpcode ( MenuOption - > ThisTag - > OpCode ) ) {
return TRUE ;
} else {
return FALSE ;
}
}
return FALSE ;
}
/**
Calculate the distance between two menus and include the skip value of StartMenu .
@ param StartMenu The link_entry pointer to start menu .
@ param EndMenu The link_entry pointer to end menu .
* */
UINTN
GetDistanceBetweenMenus (
IN LIST_ENTRY * StartMenu ,
IN LIST_ENTRY * EndMenu
)
{
LIST_ENTRY * Link ;
UI_MENU_OPTION * MenuOption ;
UINTN Distance ;
Distance = 0 ;
Link = StartMenu ;
while ( Link ! = EndMenu ) {
MenuOption = MENU_OPTION_FROM_LINK ( Link ) ;
if ( MenuOption - > Row = = 0 ) {
UpdateOptionSkipLines ( MenuOption ) ;
}
Distance + = MenuOption - > Skip ;
Link = Link - > BackLink ;
}
return Distance ;
}
/**
Find the top of screen menu base on the previous record menu info .
@ param HighLightMenu The link_entry pointer to highlight menu .
@ retval Return the the link_entry pointer top of screen menu .
* */
LIST_ENTRY *
FindTopOfScreenMenuOption (
IN LIST_ENTRY * HighLightMenu
)
{
LIST_ENTRY * NewPos ;
UI_MENU_OPTION * MenuOption ;
UINTN TopRow ;
UINTN BottomRow ;
TopRow = gStatementDimensions . TopRow + SCROLL_ARROW_HEIGHT ;
BottomRow = gStatementDimensions . BottomRow - SCROLL_ARROW_HEIGHT ;
NewPos = gMenuOption . ForwardLink ;
MenuOption = MENU_OPTION_FROM_LINK ( NewPos ) ;
while ( ! IsTopOfScreeMenuOption ( MenuOption ) ) {
NewPos = NewPos - > ForwardLink ;
if ( NewPos = = & gMenuOption ) {
//
// Not Found it, break
//
break ;
}
MenuOption = MENU_OPTION_FROM_LINK ( NewPos ) ;
}
//
// Last time top of screen menu has disappeared.
//
if ( NewPos = = & gMenuOption ) {
return NULL ;
}
//
// Check whether highlight menu and top of screen menu can be shown within one page,
// if can't, return NULL to re-calcaulate the top of scrren menu. Because some new menus
// may be dynamically inserted between highlightmenu and previous top of screen menu,
// So previous record top of screen menu is not appropriate for current display.
//
if ( GetDistanceBetweenMenus ( HighLightMenu , NewPos ) + 1 > BottomRow - TopRow ) {
return NULL ;
}
return NewPos ;
}
/**
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 UINTN * SkipValue
)
{
UINTN TopRow ;
UINTN BottomRow ;
UI_MENU_OPTION * MenuOption ;
UINTN TmpValue ;
TopRow = gStatementDimensions . TopRow + SCROLL_ARROW_HEIGHT ;
BottomRow = gStatementDimensions . BottomRow - SCROLL_ARROW_HEIGHT ;
//
// When option mismatch happens,there exist two cases,one is reenter the form, just like the if case below,
// and the other is exit current form and enter last form, it can be covered by the else case.
//
if ( gMisMatch & & gFormData - > HiiHandle = = gHighligthMenuInfo . HiiHandle & & gFormData - > FormId = = gHighligthMenuInfo . FormId ) {
//
// Reenter caused by option mismatch or auto exit caused by refresh form(refresh interval/guid),
// base on the record highlight info to find the highlight menu.
//
* HighlightMenu = FindHighLightMenuOption ( NULL ) ;
if ( * HighlightMenu ! = NULL ) {
//
// Update skip info for this highlight menu.
//
MenuOption = MENU_OPTION_FROM_LINK ( * HighlightMenu ) ;
UpdateOptionSkipLines ( MenuOption ) ;
//
// Found the last time highlight menu.
//
* TopOfScreen = FindTopOfScreenMenuOption ( * HighlightMenu ) ;
if ( * TopOfScreen ! = NULL ) {
//
// Found the last time selectable top of screen menu.
//
AdjustDateAndTimePosition ( TRUE , TopOfScreen ) ;
MenuOption = MENU_OPTION_FROM_LINK ( * TopOfScreen ) ;
UpdateOptionSkipLines ( MenuOption ) ;
* SkipValue = gHighligthMenuInfo . SkipValue ;
} else {
//
// Not found last time top of screen menu, so base on current highlight menu
// to find the new top of screen menu.
// Make the current highlight menu at the bottom of the form to calculate the
// top of screen menu.
//
if ( MenuOption - > Skip > = BottomRow - TopRow ) {
* TopOfScreen = * HighlightMenu ;
TmpValue = 0 ;
} else {
* TopOfScreen = FindTopOfScreenMenu ( * HighlightMenu , BottomRow - TopRow - MenuOption - > Skip , & TmpValue ) ;
}
* SkipValue = TmpValue ;
}
} else {
//
// Last time highlight menu has disappear, find the first highlightable menu as the default one.
//
* HighlightMenu = gMenuOption . ForwardLink ;
if ( ! IsListEmpty ( & gMenuOption ) ) {
MoveToNextStatement ( FALSE , HighlightMenu , BottomRow - TopRow , TRUE ) ;
}
* TopOfScreen = gMenuOption . ForwardLink ;
* SkipValue = 0 ;
}
} else if ( FormData - > HighLightedStatement ! = NULL ) {
if ( IsSavedHighlightStatement ( FormData - > HighLightedStatement ) ) {
//
// Input highlight menu is same as last time highlight menu.
// Base on last time highlight menu to set the top of screen menu and highlight menu.
//
* HighlightMenu = FindHighLightMenuOption ( NULL ) ;
ASSERT ( * HighlightMenu ! = NULL ) ;
//
// Update skip info for this highlight menu.
//
MenuOption = MENU_OPTION_FROM_LINK ( * HighlightMenu ) ;
UpdateOptionSkipLines ( MenuOption ) ;
* TopOfScreen = FindTopOfScreenMenuOption ( * HighlightMenu ) ;
if ( * TopOfScreen = = NULL ) {
//
// Not found last time top of screen menu, so base on current highlight menu
// to find the new top of screen menu.
// Make the current highlight menu at the bottom of the form to calculate the
// top of screen menu.
//
if ( MenuOption - > Skip > = BottomRow - TopRow ) {
* TopOfScreen = * HighlightMenu ;
TmpValue = 0 ;
} else {
* TopOfScreen = FindTopOfScreenMenu ( * HighlightMenu , BottomRow - TopRow - MenuOption - > Skip , & TmpValue ) ;
}
* SkipValue = TmpValue ;
} else {
AdjustDateAndTimePosition ( TRUE , TopOfScreen ) ;
MenuOption = MENU_OPTION_FROM_LINK ( * TopOfScreen ) ;
UpdateOptionSkipLines ( MenuOption ) ;
* SkipValue = gHighligthMenuInfo . SkipValue ;
}
AdjustDateAndTimePosition ( TRUE , TopOfScreen ) ;
} else {
//
// Input highlight menu is not save as last time highlight menu.
//
* HighlightMenu = FindHighLightMenuOption ( FormData - > HighLightedStatement ) ;
MenuOption = MENU_OPTION_FROM_LINK ( * HighlightMenu ) ;
UpdateOptionSkipLines ( MenuOption ) ;
//
// Make the current highlight menu at the bottom of the form to calculate the
// top of screen menu.
//
if ( MenuOption - > Skip > = BottomRow - TopRow ) {
* TopOfScreen = * HighlightMenu ;
TmpValue = 0 ;
} else {
* TopOfScreen = FindTopOfScreenMenu ( * HighlightMenu , BottomRow - TopRow - MenuOption - > Skip , & TmpValue ) ;
}
* SkipValue = TmpValue ;
}
AdjustDateAndTimePosition ( TRUE , TopOfScreen ) ;
} else {
//
// If not has input highlight statement, just return the first one in this form.
//
* TopOfScreen = gMenuOption . ForwardLink ;
* HighlightMenu = gMenuOption . ForwardLink ;
if ( ! IsListEmpty ( & gMenuOption ) ) {
MoveToNextStatement ( FALSE , HighlightMenu , BottomRow - TopRow , TRUE ) ;
}
* SkipValue = 0 ;
}
gMisMatch = FALSE ;
//
// First enter to show the menu, update highlight info.
//
UpdateHighlightMenuInfo ( * HighlightMenu , * TopOfScreen , * SkipValue ) ;
}
/**
Record the highlight menu and top of screen menu info .
@ param Highlight The menu opton which is highlight .
@ param TopOfScreen The menu opton which is at the top of the form .
@ param SkipValue The skip line info for the top of screen menu .
* */
VOID
UpdateHighlightMenuInfo (
IN LIST_ENTRY * Highlight ,
IN LIST_ENTRY * TopOfScreen ,
IN UINTN SkipValue
)
{
UI_MENU_OPTION * MenuOption ;
FORM_DISPLAY_ENGINE_STATEMENT * Statement ;
gHighligthMenuInfo . HiiHandle = gFormData - > HiiHandle ;
gHighligthMenuInfo . FormId = gFormData - > FormId ;
gHighligthMenuInfo . SkipValue = ( UINT16 ) SkipValue ;
if ( ! IsListEmpty ( & gMenuOption ) ) {
MenuOption = MENU_OPTION_FROM_LINK ( Highlight ) ;
Statement = MenuOption - > ThisTag ;
gUserInput - > SelectedStatement = Statement ;
gHighligthMenuInfo . HLTSequence = MenuOption - > Sequence ;
gHighligthMenuInfo . HLTQuestionId = GetQuestionIdInfo ( Statement - > OpCode ) ;
if ( gHighligthMenuInfo . HLTQuestionId = = 0 ) {
//
// if question id == 0, save the opcode buffer..
//
if ( gHighligthMenuInfo . HLTOpCode ! = NULL ) {
2020-04-23 11:08:10 +02:00
FreePool ( gHighligthMenuInfo . HLTOpCode ) ;
2019-09-03 11:58:42 +02:00
}
2020-04-27 17:16:43 +02:00
gHighligthMenuInfo . HLTOpCode = AllocateCopyPool ( Statement - > OpCode - > Length , Statement - > OpCode ) ;
2019-09-03 11:58:42 +02:00
ASSERT ( gHighligthMenuInfo . HLTOpCode ! = NULL ) ;
gHighligthMenuInfo . HLTIndex = GetIndexInfoForOpcode ( Statement - > OpCode ) ;
}
MenuOption = MENU_OPTION_FROM_LINK ( TopOfScreen ) ;
Statement = MenuOption - > ThisTag ;
gHighligthMenuInfo . TOSQuestionId = GetQuestionIdInfo ( Statement - > OpCode ) ;
if ( gHighligthMenuInfo . TOSQuestionId = = 0 ) {
//
// if question id == 0, save the opcode buffer..
//
if ( gHighligthMenuInfo . TOSOpCode ! = NULL ) {
2020-04-23 11:08:10 +02:00
FreePool ( gHighligthMenuInfo . TOSOpCode ) ;
2019-09-03 11:58:42 +02:00
}
2020-04-27 17:16:43 +02:00
gHighligthMenuInfo . TOSOpCode = AllocateCopyPool ( Statement - > OpCode - > Length , Statement - > OpCode ) ;
2019-09-03 11:58:42 +02:00
ASSERT ( gHighligthMenuInfo . TOSOpCode ! = NULL ) ;
gHighligthMenuInfo . TOSIndex = GetIndexInfoForOpcode ( Statement - > OpCode ) ;
}
} else {
gUserInput - > SelectedStatement = NULL ;
gHighligthMenuInfo . HLTSequence = 0 ;
gHighligthMenuInfo . HLTQuestionId = 0 ;
if ( gHighligthMenuInfo . HLTOpCode ! = NULL ) {
2020-04-23 11:08:10 +02:00
FreePool ( gHighligthMenuInfo . HLTOpCode ) ;
2019-09-03 11:58:42 +02:00
}
gHighligthMenuInfo . HLTOpCode = NULL ;
gHighligthMenuInfo . HLTIndex = 0 ;
gHighligthMenuInfo . TOSQuestionId = 0 ;
if ( gHighligthMenuInfo . TOSOpCode ! = NULL ) {
2020-04-23 11:08:10 +02:00
FreePool ( gHighligthMenuInfo . TOSOpCode ) ;
2019-09-03 11:58:42 +02:00
}
gHighligthMenuInfo . TOSOpCode = NULL ;
gHighligthMenuInfo . TOSIndex = 0 ;
}
}
/**
Update attribut for this menu .
@ param MenuOption The menu opton which this attribut used to .
@ param Highlight Whether this menu will be highlight .
* */
VOID
SetDisplayAttribute (
IN UI_MENU_OPTION * MenuOption ,
IN BOOLEAN Highlight
)
{
FORM_DISPLAY_ENGINE_STATEMENT * Statement ;
Statement = MenuOption - > ThisTag ;
if ( Highlight ) {
gST - > ConOut - > SetAttribute ( gST - > ConOut , GetHighlightTextColor ( ) ) ;
return ;
}
if ( MenuOption - > GrayOut ) {
gST - > ConOut - > SetAttribute ( gST - > ConOut , GetGrayedTextColor ( ) ) ;
} else {
if ( Statement - > OpCode - > OpCode = = EFI_IFR_SUBTITLE_OP ) {
gST - > ConOut - > SetAttribute ( gST - > ConOut , GetSubTitleTextColor ( ) ) ;
} else {
gST - > ConOut - > SetAttribute ( gST - > ConOut , GetFieldTextColor ( ) ) ;
}
}
}
/**
Print string for this menu option .
@ param MenuOption The menu opton which this attribut used to .
@ param Col The column that this string will be print at .
@ param Row The row that this string will be print at .
@ param String The string which need to print .
@ param Width The width need to print , if string is less than the
width , the block space will be used .
@ param Highlight Whether this menu will be highlight .
* */
VOID
DisplayMenuString (
IN UI_MENU_OPTION * MenuOption ,
IN UINTN Col ,
IN UINTN Row ,
IN CHAR16 * String ,
IN UINTN Width ,
IN BOOLEAN Highlight
)
{
UINTN Length ;
//
// Print string with normal color.
//
if ( ! Highlight ) {
PrintStringAtWithWidth ( Col , Row , String , Width ) ;
return ;
}
//
// Print the highlight menu string.
// First print the highlight string.
//
SetDisplayAttribute ( MenuOption , TRUE ) ;
Length = PrintStringAt ( Col , Row , String ) ;
//
// Second, clean the empty after the string.
//
SetDisplayAttribute ( MenuOption , FALSE ) ;
PrintStringAtWithWidth ( Col + Length , Row , L " " , Width - Length ) ;
}
/**
Check whether this menu can has option string .
@ param MenuOption The menu opton which this attribut used to .
@ retval TRUE This menu option can have option string .
@ retval FALSE This menu option can ' t have option string .
* */
BOOLEAN
HasOptionString (
IN UI_MENU_OPTION * MenuOption
)
{
FORM_DISPLAY_ENGINE_STATEMENT * Statement ;
CHAR16 * String ;
UINTN Size ;
EFI_IFR_TEXT * TestOp ;
Size = 0 ;
Statement = MenuOption - > ThisTag ;
//
// 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 ) ;
2020-04-23 11:08:10 +02:00
FreePool ( String ) ;
2019-09-03 11:58:42 +02:00
}
}
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 ) )
) {
return FALSE ;
}
return TRUE ;
}
/**
Double confirm with user about the action .
@ param Action The user input action .
@ retval TRUE User confirm with the input or not need user confirm .
@ retval FALSE User want ignore this input .
* */
BOOLEAN
FxConfirmPopup (
IN UINT32 Action
)
{
EFI_INPUT_KEY Key ;
CHAR16 * CfmStr ;
UINTN CfmStrLen ;
UINT32 CheckFlags ;
BOOLEAN RetVal ;
UINTN CatLen ;
UINTN MaxLen ;
CfmStrLen = 0 ;
CatLen = StrLen ( gConfirmMsgConnect ) ;
//
// Below action need extra popup dialog to confirm.
//
CheckFlags = BROWSER_ACTION_DISCARD |
BROWSER_ACTION_DEFAULT |
BROWSER_ACTION_SUBMIT |
BROWSER_ACTION_RESET |
BROWSER_ACTION_EXIT ;
//
// Not need to confirm with user, just return TRUE.
//
if ( ( Action & CheckFlags ) = = 0 ) {
return TRUE ;
}
if ( ( Action & BROWSER_ACTION_DISCARD ) = = BROWSER_ACTION_DISCARD ) {
CfmStrLen + = StrLen ( gConfirmDiscardMsg ) ;
}
if ( ( Action & BROWSER_ACTION_DEFAULT ) = = BROWSER_ACTION_DEFAULT ) {
if ( CfmStrLen ! = 0 ) {
CfmStrLen + = CatLen ;
}
CfmStrLen + = StrLen ( gConfirmDefaultMsg ) ;
}
if ( ( Action & BROWSER_ACTION_SUBMIT ) = = BROWSER_ACTION_SUBMIT ) {
if ( CfmStrLen ! = 0 ) {
CfmStrLen + = CatLen ;
}
CfmStrLen + = StrLen ( gConfirmSubmitMsg ) ;
}
if ( ( Action & BROWSER_ACTION_RESET ) = = BROWSER_ACTION_RESET ) {
if ( CfmStrLen ! = 0 ) {
CfmStrLen + = CatLen ;
}
CfmStrLen + = StrLen ( gConfirmResetMsg ) ;
}
if ( ( Action & BROWSER_ACTION_EXIT ) = = BROWSER_ACTION_EXIT ) {
if ( CfmStrLen ! = 0 ) {
CfmStrLen + = CatLen ;
}
CfmStrLen + = StrLen ( gConfirmExitMsg ) ;
}
//
// Allocate buffer to save the string.
// String + "?" + "\0"
//
MaxLen = CfmStrLen + 1 + 1 ;
2020-04-28 12:49:24 +02:00
CfmStr = AllocateZeroPool ( MaxLen * sizeof ( CHAR16 ) ) ;
2019-09-03 11:58:42 +02:00
ASSERT ( CfmStr ! = NULL ) ;
if ( ( Action & BROWSER_ACTION_DISCARD ) = = BROWSER_ACTION_DISCARD ) {
StrCpyS ( CfmStr , MaxLen , gConfirmDiscardMsg ) ;
}
if ( ( Action & BROWSER_ACTION_DEFAULT ) = = BROWSER_ACTION_DEFAULT ) {
if ( CfmStr [ 0 ] ! = 0 ) {
StrCatS ( CfmStr , MaxLen , gConfirmMsgConnect ) ;
StrCatS ( CfmStr , MaxLen , gConfirmDefaultMsg2nd ) ;
} else {
StrCpyS ( CfmStr , MaxLen , gConfirmDefaultMsg ) ;
}
}
if ( ( Action & BROWSER_ACTION_SUBMIT ) = = BROWSER_ACTION_SUBMIT ) {
if ( CfmStr [ 0 ] ! = 0 ) {
StrCatS ( CfmStr , MaxLen , gConfirmMsgConnect ) ;
StrCatS ( CfmStr , MaxLen , gConfirmSubmitMsg2nd ) ;
} else {
StrCpyS ( CfmStr , MaxLen , gConfirmSubmitMsg ) ;
}
}
if ( ( Action & BROWSER_ACTION_RESET ) = = BROWSER_ACTION_RESET ) {
if ( CfmStr [ 0 ] ! = 0 ) {
StrCatS ( CfmStr , MaxLen , gConfirmMsgConnect ) ;
StrCatS ( CfmStr , MaxLen , gConfirmResetMsg2nd ) ;
} else {
StrCpyS ( CfmStr , MaxLen , gConfirmResetMsg ) ;
}
}
if ( ( Action & BROWSER_ACTION_EXIT ) = = BROWSER_ACTION_EXIT ) {
if ( CfmStr [ 0 ] ! = 0 ) {
StrCatS ( CfmStr , MaxLen , gConfirmMsgConnect ) ;
StrCatS ( CfmStr , MaxLen , gConfirmExitMsg2nd ) ;
} else {
StrCpyS ( CfmStr , MaxLen , gConfirmExitMsg ) ;
}
}
StrCatS ( CfmStr , MaxLen , gConfirmMsgEnd ) ;
do {
CreateDialog ( & Key , gEmptyString , CfmStr , gConfirmOpt , gEmptyString , NULL ) ;
} while ( ( ( Key . UnicodeChar | UPPER_LOWER_CASE_OFFSET ) ! = ( gConfirmOptYes [ 0 ] | UPPER_LOWER_CASE_OFFSET ) ) & &
( ( Key . UnicodeChar | UPPER_LOWER_CASE_OFFSET ) ! = ( gConfirmOptNo [ 0 ] | UPPER_LOWER_CASE_OFFSET ) ) & &
( Key . ScanCode ! = SCAN_ESC ) ) ;
if ( ( Key . UnicodeChar | UPPER_LOWER_CASE_OFFSET ) = = ( gConfirmOptYes [ 0 ] | UPPER_LOWER_CASE_OFFSET ) ) {
RetVal = TRUE ;
} else {
RetVal = FALSE ;
}
2020-04-23 11:08:10 +02:00
FreePool ( CfmStr ) ;
2019-09-03 11:58:42 +02:00
return RetVal ;
}
/**
Print string for this menu option .
@ param MenuOption The menu opton which this attribut used to .
@ param SkipWidth The skip width between the left to the start of the prompt .
@ param BeginCol The begin column for one menu .
@ param SkipLine The skip line for this menu .
@ param BottomRow The bottom row for this form .
@ param Highlight Whether this menu will be highlight .
@ param UpdateCol Whether need to update the column info for Date / Time .
@ retval EFI_SUCESSS Process the user selection success .
* */
EFI_STATUS
DisplayOneMenu (
IN UI_MENU_OPTION * MenuOption ,
IN UINTN SkipWidth ,
IN UINTN BeginCol ,
IN UINTN SkipLine ,
IN UINTN BottomRow ,
IN BOOLEAN Highlight ,
IN BOOLEAN UpdateCol
)
{
FORM_DISPLAY_ENGINE_STATEMENT * Statement ;
UINTN Index ;
UINT16 Width ;
UINT16 PromptWidth ;
CHAR16 * StringPtr ;
CHAR16 * OptionString ;
CHAR16 * OutputString ;
UINT16 GlyphWidth ;
UINTN Temp ;
UINTN Temp2 ;
UINTN Temp3 ;
EFI_STATUS Status ;
UINTN Row ;
BOOLEAN IsProcessingFirstRow ;
UINTN Col ;
UINTN PromptLineNum ;
UINTN OptionLineNum ;
CHAR16 AdjustValue ;
UINTN MaxRow ;
Statement = MenuOption - > ThisTag ;
Temp = SkipLine ;
Temp2 = SkipLine ;
Temp3 = SkipLine ;
AdjustValue = 0 ;
PromptLineNum = 0 ;
OptionLineNum = 0 ;
MaxRow = 0 ;
IsProcessingFirstRow = TRUE ;
//
// Set default color.
//
SetDisplayAttribute ( MenuOption , FALSE ) ;
//
// 1. Paint the option string.
//
Status = ProcessOptions ( MenuOption , FALSE , & OptionString , FALSE ) ;
2020-04-23 11:08:10 +02:00
if ( EFI_ERROR ( Status ) ) {
2019-09-03 11:58:42 +02:00
return Status ;
}
if ( OptionString ! = NULL ) {
if ( Statement - > OpCode - > OpCode = = EFI_IFR_DATE_OP | | Statement - > OpCode - > OpCode = = EFI_IFR_TIME_OP ) {
//
// Adjust option string for date/time opcode.
//
ProcessStringForDateTime ( MenuOption , OptionString , UpdateCol ) ;
}
Width = ( UINT16 ) gOptionBlockWidth - 1 ;
Row = MenuOption - > Row ;
GlyphWidth = 1 ;
OptionLineNum = 0 ;
for ( Index = 0 ; GetLineByWidth ( OptionString , Width , & GlyphWidth , & Index , & OutputString ) ! = 0x0000 ; ) {
if ( ( ( Temp2 = = 0 ) ) & & ( Row < = BottomRow ) ) {
if ( Statement - > OpCode - > OpCode = = EFI_IFR_DATE_OP | | Statement - > OpCode - > OpCode = = EFI_IFR_TIME_OP ) {
//
// For date/time question, it has three menu options for this qustion.
// The first/second menu options with the skip value is 0. the last one
// with skip value is 1.
//
if ( MenuOption - > Skip ! = 0 ) {
//
// For date/ time, print the last past (year for date and second for time)
// - 7 means skip [##/##/ for date and [##:##: for time.
//
DisplayMenuString ( MenuOption , MenuOption - > OptCol , Row , OutputString , Width + 1 - 7 , Highlight ) ;
} else {
//
// For date/ time, print the first and second past (year for date and second for time)
// The OutputString has a NARROW_CHAR or WIDE_CHAR at the begin of the string,
// so need to - 1 to remove it, otherwise, it will clean 1 extr char follow it.
DisplayMenuString ( MenuOption , MenuOption - > OptCol , Row , OutputString , StrLen ( OutputString ) - 1 , Highlight ) ;
}
} else {
DisplayMenuString ( MenuOption , MenuOption - > OptCol , Row , OutputString , Width + 1 , Highlight ) ;
}
OptionLineNum + + ;
}
//
// 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 - MenuOption - > Row ) > = MenuOption - > Skip ) {
MenuOption - > Skip + + ;
}
}
}
2020-04-23 11:08:10 +02:00
FreePool ( OutputString ) ;
2019-09-03 11:58:42 +02:00
if ( Temp2 ! = 0 ) {
Temp2 - - ;
}
}
Highlight = FALSE ;
2020-04-23 11:08:10 +02:00
FreePool ( OptionString ) ;
2019-09-03 11:58:42 +02:00
}
//
// 2. Paint the description.
//
PromptWidth = GetWidth ( MenuOption , & AdjustValue ) ;
Row = MenuOption - > Row ;
GlyphWidth = 1 ;
PromptLineNum = 0 ;
if ( MenuOption - > Description = = NULL | | MenuOption - > Description [ 0 ] = = ' \0 ' ) {
PrintStringAtWithWidth ( BeginCol , Row , L " " , PromptWidth + AdjustValue + SkipWidth ) ;
PromptLineNum + + ;
} else {
for ( Index = 0 ; GetLineByWidth ( MenuOption - > Description , PromptWidth , & GlyphWidth , & Index , & OutputString ) ! = 0x0000 ; ) {
if ( ( Temp = = 0 ) & & ( Row < = BottomRow ) ) {
//
// 1.Clean the start LEFT_SKIPPED_COLUMNS
//
PrintStringAtWithWidth ( BeginCol , Row , L " " , SkipWidth ) ;
if ( Statement - > OpCode - > OpCode = = EFI_IFR_REF_OP & & MenuOption - > Col > = 2 & & IsProcessingFirstRow ) {
//
// Print Arrow for Goto button.
//
PrintCharAt (
MenuOption - > Col - 2 ,
Row ,
GEOMETRICSHAPE_RIGHT_TRIANGLE
) ;
IsProcessingFirstRow = FALSE ;
}
DisplayMenuString ( MenuOption , MenuOption - > Col , Row , OutputString , PromptWidth + AdjustValue , Highlight ) ;
PromptLineNum + + ;
}
//
// 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 + + ;
}
}
2020-04-23 11:08:10 +02:00
FreePool ( OutputString ) ;
2019-09-03 11:58:42 +02:00
if ( Temp ! = 0 ) {
Temp - - ;
}
}
Highlight = FALSE ;
}
//
// 3. 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 - 1 ;
Row = MenuOption - > Row ;
GlyphWidth = 1 ;
OptionLineNum = 0 ;
for ( Index = 0 ; GetLineByWidth ( StringPtr , Width , & GlyphWidth , & Index , & OutputString ) ! = 0x0000 ; ) {
if ( ( Temp3 = = 0 ) & & ( Row < = BottomRow ) ) {
DisplayMenuString ( MenuOption , MenuOption - > OptCol , Row , OutputString , Width + 1 , Highlight ) ;
OptionLineNum + + ;
}
//
// 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 + + ;
//
// If the rows for text two is greater than or equal to the skip value, increase the skip value
//
if ( ( Row - MenuOption - > Row ) > = MenuOption - > Skip ) {
MenuOption - > Skip + + ;
}
}
}
2020-04-23 11:08:10 +02:00
FreePool ( OutputString ) ;
2019-09-03 11:58:42 +02:00
if ( Temp3 ! = 0 ) {
Temp3 - - ;
}
}
2020-04-23 11:08:10 +02:00
FreePool ( StringPtr ) ;
2019-09-03 11:58:42 +02:00
}
//
// 4.Line number for Option string and prompt string are not equal.
// Clean the column whose line number is less.
//
if ( HasOptionString ( MenuOption ) & & ( OptionLineNum ! = PromptLineNum ) ) {
Col = OptionLineNum < PromptLineNum ? MenuOption - > OptCol : BeginCol ;
Row = ( OptionLineNum < PromptLineNum ? OptionLineNum : PromptLineNum ) + MenuOption - > Row ;
Width = ( UINT16 ) ( OptionLineNum < PromptLineNum ? gOptionBlockWidth : PromptWidth + AdjustValue + SkipWidth ) ;
MaxRow = ( OptionLineNum < PromptLineNum ? PromptLineNum : OptionLineNum ) + MenuOption - > Row - 1 ;
while ( Row < = MaxRow ) {
DisplayMenuString ( MenuOption , Col , Row + + , L " " , Width , FALSE ) ;
}
}
return EFI_SUCCESS ;
}
/**
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
)
{
UINTN SkipValue ;
INTN Difference ;
UINTN DistanceValue ;
UINTN Row ;
UINTN Col ;
UINTN Temp ;
UINTN Temp2 ;
UINTN TopRow ;
UINTN BottomRow ;
UINTN Index ;
CHAR16 * StringPtr ;
CHAR16 * StringRightPtr ;
CHAR16 * StringErrorPtr ;
CHAR16 * OptionString ;
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_CONTROL_FLAG ControlFlag ;
UI_SCREEN_OPERATION ScreenOperation ;
FORM_DISPLAY_ENGINE_STATEMENT * Statement ;
BROWSER_HOT_KEY * HotKey ;
UINTN HelpPageIndex ;
UINTN HelpPageCount ;
UINTN RowCount ;
UINTN HelpLine ;
UINTN HelpHeaderLine ;
UINTN HelpBottomLine ;
BOOLEAN MultiHelpPage ;
UINT16 EachLineWidth ;
UINT16 HeaderLineWidth ;
UINT16 BottomLineWidth ;
EFI_STRING_ID HelpInfo ;
UI_EVENT_TYPE EventType ;
BOOLEAN SkipHighLight ;
EFI_HII_VALUE * StatementValue ;
EventType = UIEventNone ;
Status = EFI_SUCCESS ;
HelpString = NULL ;
HelpHeaderString = NULL ;
HelpBottomString = NULL ;
OptionString = NULL ;
ScreenOperation = UiNoOperation ;
NewLine = TRUE ;
HelpPageCount = 0 ;
HelpLine = 0 ;
RowCount = 0 ;
HelpBottomLine = 0 ;
HelpHeaderLine = 0 ;
HelpPageIndex = 0 ;
MultiHelpPage = FALSE ;
EachLineWidth = 0 ;
HeaderLineWidth = 0 ;
BottomLineWidth = 0 ;
UpArrow = FALSE ;
DownArrow = FALSE ;
SkipValue = 0 ;
SkipHighLight = FALSE ;
NextMenuOption = NULL ;
SavedMenuOption = NULL ;
HotKey = NULL ;
Repaint = TRUE ;
MenuOption = NULL ;
gModalSkipColumn = ( CHAR16 ) ( gStatementDimensions . RightColumn - gStatementDimensions . LeftColumn ) / 6 ;
ZeroMem ( & Key , sizeof ( EFI_INPUT_KEY ) ) ;
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 + gModalSkipColumn ;
} else {
Col = gStatementDimensions . LeftColumn + LEFT_SKIPPED_COLUMNS ;
}
FindTopMenu ( FormData , & TopOfScreen , & NewPos , & SkipValue ) ;
if ( ! IsListEmpty ( & gMenuOption ) ) {
NextMenuOption = MENU_OPTION_FROM_LINK ( NewPos ) ;
gUserInput - > SelectedStatement = NextMenuOption - > ThisTag ;
}
gST - > ConOut - > EnableCursor ( gST - > ConOut , FALSE ) ;
ControlFlag = CfInitialization ;
while ( TRUE ) {
switch ( ControlFlag ) {
case CfInitialization :
if ( ( gOldFormEntry . HiiHandle ! = FormData - > HiiHandle ) | |
( ! CompareGuid ( & gOldFormEntry . FormSetGuid , & FormData - > FormSetGuid ) ) ) {
//
// Clear Statement range if different formset is painted.
//
ClearLines (
gStatementDimensions . LeftColumn ,
gStatementDimensions . RightColumn ,
TopRow - SCROLL_ARROW_HEIGHT ,
BottomRow + SCROLL_ARROW_HEIGHT ,
GetFieldTextColor ( )
) ;
}
ControlFlag = CfRepaint ;
break ;
case CfRepaint :
ControlFlag = CfRefreshHighLight ;
if ( Repaint ) {
//
// Display menu
//
DownArrow = FALSE ;
UpArrow = FALSE ;
Row = TopRow ;
gST - > ConOut - > SetAttribute ( gST - > ConOut , GetFieldTextColor ( ) ) ;
//
// 1. Check whether need to print the arrow up.
//
if ( ! ValueIsScroll ( TRUE , TopOfScreen ) ) {
UpArrow = TRUE ;
}
if ( ( FormData - > Attribute & HII_DISPLAY_MODAL ) ! = 0 ) {
PrintStringAtWithWidth ( gStatementDimensions . LeftColumn + gModalSkipColumn , TopRow - 1 , L " " , gStatementDimensions . RightColumn - gStatementDimensions . LeftColumn - 2 * gModalSkipColumn ) ;
} else {
PrintStringAtWithWidth ( gStatementDimensions . LeftColumn , TopRow - 1 , L " " , gStatementDimensions . RightColumn - gStatementDimensions . LeftColumn ) ;
}
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 ( ) ) ;
}
//
// 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 = gStatementDimensions . LeftColumn + LEFT_SKIPPED_COLUMNS + gPromptBlockWidth + gModalSkipColumn ;
} else {
MenuOption - > OptCol = gStatementDimensions . LeftColumn + LEFT_SKIPPED_COLUMNS + gPromptBlockWidth ;
}
if ( MenuOption - > NestInStatement ) {
MenuOption - > Col + = SUBTITLE_INDENT ;
}
//
// Save the highlight menu, will be used in CfRefreshHighLight case.
//
if ( Link = = NewPos ) {
SavedMenuOption = MenuOption ;
SkipHighLight = TRUE ;
}
if ( ( FormData - > Attribute & HII_DISPLAY_MODAL ) ! = 0 ) {
Status = DisplayOneMenu ( MenuOption ,
MenuOption - > Col - gStatementDimensions . LeftColumn ,
gStatementDimensions . LeftColumn + gModalSkipColumn ,
Link = = TopOfScreen ? SkipValue : 0 ,
BottomRow ,
( BOOLEAN ) ( ( Link = = NewPos ) & & IsSelectable ( MenuOption ) ) ,
TRUE
) ;
} else {
Status = DisplayOneMenu ( MenuOption ,
MenuOption - > Col - gStatementDimensions . LeftColumn ,
gStatementDimensions . LeftColumn ,
Link = = TopOfScreen ? SkipValue : 0 ,
BottomRow ,
( BOOLEAN ) ( ( Link = = NewPos ) & & IsSelectable ( MenuOption ) ) ,
TRUE
) ;
}
2020-04-23 11:08:10 +02:00
if ( EFI_ERROR ( Status ) ) {
2019-09-03 11:58:42 +02:00
if ( gMisMatch ) {
return EFI_SUCCESS ;
} else {
return Status ;
}
}
//
// 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 ;
}
}
//
// 3. Menus in this form may not cover all form, clean the remain field.
//
while ( Row < = BottomRow ) {
if ( ( FormData - > Attribute & HII_DISPLAY_MODAL ) ! = 0 ) {
PrintStringAtWithWidth ( gStatementDimensions . LeftColumn + gModalSkipColumn , Row + + , L " " , gStatementDimensions . RightColumn - gStatementDimensions . LeftColumn - 2 * gModalSkipColumn ) ;
} else {
PrintStringAtWithWidth ( gStatementDimensions . LeftColumn , Row + + , L " " , gStatementDimensions . RightColumn - gHelpBlockWidth - gStatementDimensions . LeftColumn ) ;
}
}
//
// 4. Print the down arrow row.
//
if ( ( FormData - > Attribute & HII_DISPLAY_MODAL ) ! = 0 ) {
PrintStringAtWithWidth ( gStatementDimensions . LeftColumn + gModalSkipColumn , BottomRow + 1 , L " " , gStatementDimensions . RightColumn - gStatementDimensions . LeftColumn - 2 * + gModalSkipColumn ) ;
} else {
PrintStringAtWithWidth ( gStatementDimensions . LeftColumn , BottomRow + 1 , L " " , gStatementDimensions . RightColumn - gStatementDimensions . LeftColumn ) ;
}
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 ;
ASSERT ( NewPos ! = NULL ) ;
UpdateHighlightMenuInfo ( NewPos , TopOfScreen , SkipValue ) ;
if ( SkipHighLight ) {
SkipHighLight = FALSE ;
MenuOption = SavedMenuOption ;
RefreshKeyHelp ( gFormData , SavedMenuOption - > ThisTag , FALSE ) ;
break ;
}
if ( IsListEmpty ( & gMenuOption ) ) {
//
// No menu option, just update the hotkey filed.
//
RefreshKeyHelp ( gFormData , NULL , FALSE ) ;
break ;
}
if ( MenuOption ! = NULL & & TopOfScreen = = & MenuOption - > Link ) {
Temp = SkipValue ;
} else {
Temp = 0 ;
}
if ( NewPos = = TopOfScreen ) {
Temp2 = SkipValue ;
} else {
Temp2 = 0 ;
}
if ( MenuOption = = NULL | | NewPos ! = & MenuOption - > Link ) {
if ( MenuOption ! = NULL ) {
//
// Remove the old highlight menu.
//
Status = DisplayOneMenu ( MenuOption ,
MenuOption - > Col - gStatementDimensions . LeftColumn ,
gStatementDimensions . LeftColumn ,
Temp ,
BottomRow ,
FALSE ,
FALSE
) ;
}
//
// This is the current selected statement
//
MenuOption = MENU_OPTION_FROM_LINK ( NewPos ) ;
RefreshKeyHelp ( gFormData , MenuOption - > ThisTag , FALSE ) ;
if ( ! IsSelectable ( MenuOption ) ) {
break ;
}
Status = DisplayOneMenu ( MenuOption ,
MenuOption - > Col - gStatementDimensions . LeftColumn ,
gStatementDimensions . LeftColumn ,
Temp2 ,
BottomRow ,
TRUE ,
FALSE
) ;
}
break ;
case CfUpdateHelpString :
ControlFlag = CfPrepareToReadKey ;
if ( ( FormData - > Attribute & HII_DISPLAY_MODAL ) ! = 0 ) {
break ;
}
//
// NewLine means only update highlight menu (remove old highlight and highlith
// the new one), not need to full repain the form.
//
if ( Repaint | | NewLine ) {
if ( IsListEmpty ( & gMenuOption ) ) {
//
// Don't print anything if no mwnu option.
//
StringPtr = GetToken ( STRING_TOKEN ( EMPTY_STRING ) , gHiiHandle ) ;
} else {
//
// 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 ;
Statement = MenuOption - > ThisTag ;
StatementValue = & Statement - > CurrentValue ;
if ( HelpInfo = = 0 | | ! IsSelectable ( MenuOption ) ) {
if ( ( Statement - > OpCode - > OpCode = = EFI_IFR_DATE_OP & & StatementValue - > Value . date . Month = = 0xff ) | | ( Statement - > OpCode - > OpCode = = EFI_IFR_TIME_OP & & StatementValue - > Value . time . Hour = = 0xff ) ) {
StringPtr = GetToken ( STRING_TOKEN ( GET_TIME_FAIL ) , gHiiHandle ) ;
} else {
StringPtr = GetToken ( STRING_TOKEN ( EMPTY_STRING ) , gHiiHandle ) ;
}
} else {
if ( ( Statement - > OpCode - > OpCode = = EFI_IFR_DATE_OP & & StatementValue - > Value . date . Month = = 0xff ) | | ( Statement - > OpCode - > OpCode = = EFI_IFR_TIME_OP & & StatementValue - > Value . time . Hour = = 0xff ) ) {
StringRightPtr = GetToken ( HelpInfo , gFormData - > HiiHandle ) ;
StringErrorPtr = GetToken ( STRING_TOKEN ( GET_TIME_FAIL ) , gHiiHandle ) ;
2020-04-28 12:49:24 +02:00
StringPtr = AllocateZeroPool ( ( StrLen ( StringRightPtr ) + StrLen ( StringErrorPtr ) + 1 ) * sizeof ( CHAR16 ) ) ;
2019-09-03 11:58:42 +02:00
StrCpyS ( StringPtr , StrLen ( StringRightPtr ) + StrLen ( StringErrorPtr ) + 1 , StringRightPtr ) ;
StrCatS ( StringPtr , StrLen ( StringRightPtr ) + StrLen ( StringErrorPtr ) + 1 , StringErrorPtr ) ;
2020-04-23 11:08:10 +02:00
FreePool ( StringRightPtr ) ;
FreePool ( StringErrorPtr ) ;
2019-09-03 11:58:42 +02:00
} 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 ) {
2020-04-23 11:08:10 +02:00
FreePool ( HelpString ) ;
2019-09-03 11:58:42 +02:00
HelpString = NULL ;
}
HelpLine = ProcessHelpString ( StringPtr , & HelpString , & EachLineWidth , RowCount ) ;
2020-04-23 11:08:10 +02:00
FreePool ( StringPtr ) ;
2019-09-03 11:58:42 +02:00
if ( HelpLine > RowCount ) {
MultiHelpPage = TRUE ;
StringPtr = GetToken ( STRING_TOKEN ( ADJUST_HELP_PAGE_UP ) , gHiiHandle ) ;
if ( HelpHeaderString ! = NULL ) {
2020-04-23 11:08:10 +02:00
FreePool ( HelpHeaderString ) ;
2019-09-03 11:58:42 +02:00
HelpHeaderString = NULL ;
}
HelpHeaderLine = ProcessHelpString ( StringPtr , & HelpHeaderString , & HeaderLineWidth , 0 ) ;
2020-04-23 11:08:10 +02:00
FreePool ( StringPtr ) ;
2019-09-03 11:58:42 +02:00
StringPtr = GetToken ( STRING_TOKEN ( ADJUST_HELP_PAGE_DOWN ) , gHiiHandle ) ;
if ( HelpBottomString ! = NULL ) {
2020-04-23 11:08:10 +02:00
FreePool ( HelpBottomString ) ;
2019-09-03 11:58:42 +02:00
HelpBottomString = NULL ;
}
HelpBottomLine = ProcessHelpString ( StringPtr , & HelpBottomString , & BottomLineWidth , 0 ) ;
2020-04-23 11:08:10 +02:00
FreePool ( StringPtr ) ;
2019-09-03 11:58:42 +02:00
//
// Calculate the help page count.
//
if ( HelpLine > 2 * RowCount - 2 ) {
HelpPageCount = ( HelpLine - RowCount + 1 ) / ( RowCount - 2 ) + 1 ;
if ( ( HelpLine - RowCount + 1 ) % ( RowCount - 2 ) ! = 0 ) {
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 < ( ( UINT32 ) 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 < ( ( UINT32 ) 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 ) ;
2020-04-23 11:08:10 +02:00
if ( ! EFI_ERROR ( Status ) ) {
2019-09-03 11:58:42 +02:00
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 ) {
gMisMatch = TRUE ;
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.
//
ASSERT ( MenuOption ! = NULL ) ;
if ( IsListEmpty ( & gMenuOption ) | | MenuOption - > GrayOut | | MenuOption - > ReadOnly ) {
ControlFlag = CfReadKey ;
break ;
}
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 ) {
2020-04-23 11:08:10 +02:00
FreePool ( OptionString ) ;
2019-09-03 11:58:42 +02:00
}
2020-04-23 11:08:10 +02:00
if ( EFI_ERROR ( Status ) ) {
2019-09-03 11:58:42 +02:00
//
// 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 ) & & ( ScreenOperation ! = UiHotKey ) ) {
//
// If the screen has no menu items, and the user didn't select UiReset or UiHotKey
// ignore the selection and go back to reading keys.
//
if ( IsListEmpty ( & gMenuOption ) ) {
ControlFlag = CfReadKey ;
break ;
}
}
for ( Index = 0 ;
Index < ARRAY_SIZE ( gScreenOperationToControlFlag ) ;
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 ) {
2020-04-23 11:08:10 +02:00
FreePool ( OptionString ) ;
2019-09-03 11:58:42 +02:00
}
2020-04-23 11:08:10 +02:00
if ( EFI_ERROR ( Status ) ) {
2019-09-03 11:58:42 +02:00
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 ;
}
gUserInput - > Action = BROWSER_ACTION_FORM_EXIT ;
ControlFlag = CfExit ;
break ;
case CfUiHotKey :
ControlFlag = CfRepaint ;
ASSERT ( HotKey ! = NULL ) ;
if ( FxConfirmPopup ( HotKey - > Action ) ) {
gUserInput - > Action = HotKey - > Action ;
if ( ( HotKey - > Action & BROWSER_ACTION_DEFAULT ) = = BROWSER_ACTION_DEFAULT ) {
gUserInput - > DefaultId = HotKey - > DefaultId ;
}
ControlFlag = CfExit ;
} else {
Repaint = TRUE ;
NewLine = TRUE ;
ControlFlag = CfRepaint ;
}
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 ;
NewLine = TRUE ;
SavedListEntry = NewPos ;
ASSERT ( NewPos ! = NULL ) ;
MenuOption = MENU_OPTION_FROM_LINK ( NewPos ) ;
ASSERT ( MenuOption ! = NULL ) ;
//
// Adjust Date/Time position before we advance forward.
//
AdjustDateAndTimePosition ( TRUE , & NewPos ) ;
NewPos = NewPos - > BackLink ;
//
// Find next selectable menu or the first menu beyond current form.
//
Difference = MoveToNextStatement ( TRUE , & NewPos , MenuOption - > Row - TopRow , FALSE ) ;
if ( Difference < 0 ) {
//
// We hit the begining MenuOption that can be focused
// so we simply scroll to the top.
//
Repaint = TRUE ;
if ( TopOfScreen ! = gMenuOption . ForwardLink | | SkipValue ! = 0 ) {
TopOfScreen = gMenuOption . ForwardLink ;
NewPos = SavedListEntry ;
SkipValue = 0 ;
} else {
//
// Scroll up to the last page when we have arrived at top page.
//
TopOfScreen = FindTopOfScreenMenu ( gMenuOption . BackLink , BottomRow - TopRow , & SkipValue ) ;
NewPos = gMenuOption . BackLink ;
MoveToNextStatement ( TRUE , & NewPos , BottomRow - TopRow , TRUE ) ;
}
} else {
NextMenuOption = MENU_OPTION_FROM_LINK ( NewPos ) ;
if ( MenuOption - > Row < TopRow + Difference + NextMenuOption - > Skip ) {
//
// Previous focus MenuOption is above the TopOfScreen, so we need to scroll
//
TopOfScreen = NewPos ;
Repaint = TRUE ;
SkipValue = 0 ;
}
//
// Check whether new highlight menu is selectable, if not, keep highlight on the old one.
//
// BottomRow - TopRow + 1 means the total rows current forms supported.
// Difference + NextMenuOption->Skip + 1 means the distance between last highlight menu
// and new top menu. New top menu will all shows in next form, but last highlight menu
// may only shows 1 line. + 1 at right part means at least need to keep 1 line for the
// last highlight menu.
//
if ( ! IsSelectable ( NextMenuOption ) & & IsSelectable ( MenuOption ) & &
( BottomRow - TopRow + 1 > = Difference + NextMenuOption - > Skip + 1 ) ) {
NewPos = SavedListEntry ;
}
}
UpdateStatusBar ( INPUT_ERROR , FALSE ) ;
//
// If we encounter a Date/Time op-code set, rewind to the first op-code of the set.
//
AdjustDateAndTimePosition ( TRUE , & TopOfScreen ) ;
AdjustDateAndTimePosition ( TRUE , & NewPos ) ;
UpdateHighlightMenuInfo ( NewPos , TopOfScreen , SkipValue ) ;
break ;
case CfUiPageUp :
//
// SkipValue means lines is skipped when show the top menu option.
//
ControlFlag = CfRepaint ;
NewLine = TRUE ;
Repaint = TRUE ;
Link = TopOfScreen ;
//
// First minus the menu of the top screen, it's value is SkipValue.
//
if ( SkipValue > = BottomRow - TopRow + 1 ) {
//
// 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.
//
SkipValue - = BottomRow - TopRow + 1 ;
NewPos = TopOfScreen ;
break ;
} else {
Index = ( BottomRow + 1 ) - SkipValue - TopRow ;
}
TopOfScreen = FindTopOfScreenMenu ( TopOfScreen , Index , & SkipValue ) ;
NewPos = TopOfScreen ;
MoveToNextStatement ( FALSE , & NewPos , BottomRow - TopRow , FALSE ) ;
UpdateStatusBar ( INPUT_ERROR , FALSE ) ;
//
// 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 ) ;
UpdateHighlightMenuInfo ( NewPos , TopOfScreen , SkipValue ) ;
break ;
case CfUiPageDown :
//
// SkipValue means lines is skipped when show the top menu option.
//
ControlFlag = CfRepaint ;
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 ) ) {
//
// Highlight on the last menu which can be highlight.
//
Repaint = FALSE ;
MoveToNextStatement ( TRUE , & Link , Index - TopRow , TRUE ) ;
} 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 , TRUE ) ;
}
//
// Save the menu as the next highlight menu.
//
NewPos = Link ;
UpdateStatusBar ( INPUT_ERROR , FALSE ) ;
//
// 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 ) ;
UpdateHighlightMenuInfo ( NewPos , TopOfScreen , SkipValue ) ;
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 ;
NewLine = TRUE ;
if ( NewPos = = TopOfScreen ) {
Temp2 = SkipValue ;
} else {
Temp2 = 0 ;
}
SavedListEntry = NewPos ;
//
// 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.
//
AdjustDateAndTimePosition ( FALSE , & NewPos ) ;
MenuOption = MENU_OPTION_FROM_LINK ( NewPos ) ;
NewPos = NewPos - > ForwardLink ;
//
// Find the next selectable menu.
//
if ( MenuOption - > Row + MenuOption - > Skip - Temp2 > BottomRow + 1 ) {
if ( gMenuOption . ForwardLink = = NewPos | | & gMenuOption = = NewPos ) {
Difference = - 1 ;
} else {
Difference = 0 ;
}
} else {
Difference = MoveToNextStatement ( FALSE , & NewPos , BottomRow + 1 - ( MenuOption - > Row + MenuOption - > Skip - Temp2 ) , FALSE ) ;
}
if ( Difference < 0 ) {
//
// Scroll to the first page.
//
if ( TopOfScreen ! = gMenuOption . ForwardLink | | SkipValue ! = 0 ) {
TopOfScreen = gMenuOption . ForwardLink ;
Repaint = TRUE ;
MenuOption = NULL ;
} else {
MenuOption = MENU_OPTION_FROM_LINK ( SavedListEntry ) ;
}
NewPos = gMenuOption . ForwardLink ;
MoveToNextStatement ( FALSE , & NewPos , BottomRow - TopRow , TRUE ) ;
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 ) ;
UpdateHighlightMenuInfo ( NewPos , TopOfScreen , SkipValue ) ;
break ;
}
//
// Get next selected menu info.
//
AdjustDateAndTimePosition ( FALSE , & NewPos ) ;
NextMenuOption = MENU_OPTION_FROM_LINK ( NewPos ) ;
if ( NextMenuOption - > Row = = 0 ) {
UpdateOptionSkipLines ( NextMenuOption ) ;
}
//
// Calculate new highlight menu end row.
//
Temp = ( MenuOption - > Row + MenuOption - > Skip - Temp2 ) + Difference + NextMenuOption - > Skip - 1 ;
if ( Temp > BottomRow ) {
//
// Get the top screen menu info.
//
AdjustDateAndTimePosition ( FALSE , & TopOfScreen ) ;
SavedMenuOption = MENU_OPTION_FROM_LINK ( TopOfScreen ) ;
//
// Current Top screen menu occupy (SavedMenuOption->Skip - SkipValue) rows.
// Full shows the new selected menu need to skip (Temp - BottomRow - 1) rows.
//
if ( ( Temp - BottomRow ) > = ( SavedMenuOption - > Skip - SkipValue ) ) {
//
// Skip the top op-code
//
TopOfScreen = TopOfScreen - > ForwardLink ;
DistanceValue = ( 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
// Special case is the selected highlight menu has more than one form of menus.
//
while ( DistanceValue > = SavedMenuOption - > Skip & & TopOfScreen ! = NewPos ) {
//
// Since the Difference is greater than or equal to this op-code's skip value, skip it
//
DistanceValue = DistanceValue - ( 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.
//
if ( TopOfScreen ! = NewPos ) {
SkipValue = DistanceValue ;
} else {
SkipValue = 0 ;
}
} 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 ;
}
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 ;
break ;
}
MenuOption = MENU_OPTION_FROM_LINK ( SavedListEntry ) ;
//
// Check whether new highlight menu is selectable, if not, keep highlight on the old one.
//
// BottomRow - TopRow + 1 means the total rows current forms supported.
// Difference + NextMenuOption->Skip + 1 means the distance between last highlight menu
// and new top menu. New top menu will all shows in next form, but last highlight menu
// may only shows 1 line. + 1 at right part means at least need to keep 1 line for the
// last highlight menu.
//
if ( ! IsSelectable ( NextMenuOption ) & & IsSelectable ( MenuOption ) & &
( BottomRow - TopRow + 1 > = Difference + NextMenuOption - > Skip + 1 ) ) {
NewPos = SavedListEntry ;
}
UpdateStatusBar ( INPUT_ERROR , FALSE ) ;
//
// 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 ) ;
UpdateHighlightMenuInfo ( NewPos , TopOfScreen , SkipValue ) ;
break ;
case CfUiNoOperation :
ControlFlag = CfRepaint ;
break ;
case CfExit :
gST - > ConOut - > SetAttribute ( gST - > ConOut , EFI_TEXT_ATTR ( EFI_LIGHTGRAY , EFI_BLACK ) ) ;
if ( HelpString ! = NULL ) {
2020-04-23 11:08:10 +02:00
FreePool ( HelpString ) ;
2019-09-03 11:58:42 +02:00
}
if ( HelpHeaderString ! = NULL ) {
2020-04-23 11:08:10 +02:00
FreePool ( HelpHeaderString ) ;
2019-09-03 11:58:42 +02:00
}
if ( HelpBottomString ! = NULL ) {
2020-04-23 11:08:10 +02:00
FreePool ( HelpBottomString ) ;
2019-09-03 11:58:42 +02:00
}
return EFI_SUCCESS ;
default :
break ;
}
}
}
/**
Free the UI Menu Option structure data .
@ param MenuOptionList Point to the menu option list which need to be free .
* */
VOID
FreeMenuOptionData (
LIST_ENTRY * MenuOptionList
)
{
LIST_ENTRY * Link ;
UI_MENU_OPTION * Option ;
//
// Free menu option list
//
while ( ! IsListEmpty ( MenuOptionList ) ) {
Link = GetFirstNode ( MenuOptionList ) ;
Option = MENU_OPTION_FROM_LINK ( Link ) ;
if ( Option - > Description ! = NULL ) {
FreePool ( Option - > Description ) ;
}
RemoveEntryList ( & Option - > Link ) ;
2020-04-23 11:08:10 +02:00
FreePool ( Option ) ;
2019-09-03 11:58:42 +02:00
}
}
/**
Base on the browser status info to show an pop up message .
* */
VOID
BrowserStatusProcess (
VOID
)
{
CHAR16 * ErrorInfo ;
EFI_INPUT_KEY Key ;
EFI_EVENT WaitList [ 2 ] ;
EFI_EVENT RefreshIntervalEvent ;
EFI_EVENT TimeOutEvent ;
UINT8 TimeOut ;
EFI_STATUS Status ;
UINTN Index ;
WARNING_IF_CONTEXT EventContext ;
EFI_IFR_OP_HEADER * OpCodeBuf ;
EFI_STRING_ID StringToken ;
CHAR16 DiscardChange ;
CHAR16 JumpToFormSet ;
CHAR16 * PrintString ;
if ( gFormData - > BrowserStatus = = BROWSER_SUCCESS ) {
return ;
}
StringToken = 0 ;
TimeOutEvent = NULL ;
RefreshIntervalEvent = NULL ;
OpCodeBuf = NULL ;
if ( gFormData - > HighLightedStatement ! = NULL ) {
OpCodeBuf = gFormData - > HighLightedStatement - > OpCode ;
}
if ( gFormData - > BrowserStatus = = ( BROWSER_WARNING_IF ) ) {
ASSERT ( OpCodeBuf ! = NULL & & OpCodeBuf - > OpCode = = EFI_IFR_WARNING_IF_OP ) ;
TimeOut = ( ( EFI_IFR_WARNING_IF * ) OpCodeBuf ) - > TimeOut ;
StringToken = ( ( EFI_IFR_WARNING_IF * ) OpCodeBuf ) - > Warning ;
} else {
TimeOut = 0 ;
if ( ( gFormData - > BrowserStatus = = ( BROWSER_NO_SUBMIT_IF ) ) & &
( OpCodeBuf ! = NULL & & OpCodeBuf - > OpCode = = EFI_IFR_NO_SUBMIT_IF_OP ) ) {
StringToken = ( ( EFI_IFR_NO_SUBMIT_IF * ) OpCodeBuf ) - > Error ;
} else if ( ( gFormData - > BrowserStatus = = ( BROWSER_INCONSISTENT_IF ) ) & &
( OpCodeBuf ! = NULL & & OpCodeBuf - > OpCode = = EFI_IFR_INCONSISTENT_IF_OP ) ) {
StringToken = ( ( EFI_IFR_INCONSISTENT_IF * ) OpCodeBuf ) - > Error ;
}
}
if ( StringToken ! = 0 ) {
ErrorInfo = GetToken ( StringToken , gFormData - > HiiHandle ) ;
} else if ( gFormData - > ErrorString ! = NULL ) {
//
// Only used to compatible with old setup browser.
// Not use this field in new browser core.
//
ErrorInfo = gFormData - > ErrorString ;
} else {
switch ( gFormData - > BrowserStatus ) {
case BROWSER_SUBMIT_FAIL :
ErrorInfo = gSaveFailed ;
break ;
case BROWSER_FORM_NOT_FOUND :
ErrorInfo = gFormNotFound ;
break ;
case BROWSER_FORM_SUPPRESS :
ErrorInfo = gFormSuppress ;
break ;
case BROWSER_PROTOCOL_NOT_FOUND :
ErrorInfo = gProtocolNotFound ;
break ;
case BROWSER_SUBMIT_FAIL_NO_SUBMIT_IF :
ErrorInfo = gNoSubmitIfFailed ;
break ;
case BROWSER_RECONNECT_FAIL :
ErrorInfo = gReconnectFail ;
break ;
case BROWSER_RECONNECT_SAVE_CHANGES :
ErrorInfo = gReconnectConfirmChanges ;
break ;
case BROWSER_RECONNECT_REQUIRED :
ErrorInfo = gReconnectRequired ;
break ;
default :
ErrorInfo = gBrowserError ;
break ;
}
}
switch ( gFormData - > BrowserStatus ) {
case BROWSER_SUBMIT_FAIL :
case BROWSER_SUBMIT_FAIL_NO_SUBMIT_IF :
case BROWSER_RECONNECT_SAVE_CHANGES :
ASSERT ( gUserInput ! = NULL ) ;
if ( gFormData - > BrowserStatus = = ( BROWSER_SUBMIT_FAIL ) ) {
PrintString = gSaveProcess ;
JumpToFormSet = gJumpToFormSet [ 0 ] ;
DiscardChange = gDiscardChange [ 0 ] ;
} else if ( gFormData - > BrowserStatus = = ( BROWSER_RECONNECT_SAVE_CHANGES ) ) {
PrintString = gChangesOpt ;
JumpToFormSet = gConfirmOptYes [ 0 ] ;
DiscardChange = gConfirmOptNo [ 0 ] ;
} else {
PrintString = gSaveNoSubmitProcess ;
JumpToFormSet = gCheckError [ 0 ] ;
DiscardChange = gDiscardChange [ 0 ] ;
}
do {
CreateDialog ( & Key , gEmptyString , ErrorInfo , PrintString , gEmptyString , NULL ) ;
} while ( ( ( Key . UnicodeChar | UPPER_LOWER_CASE_OFFSET ) ! = ( DiscardChange | UPPER_LOWER_CASE_OFFSET ) ) & &
( ( Key . UnicodeChar | UPPER_LOWER_CASE_OFFSET ) ! = ( JumpToFormSet | UPPER_LOWER_CASE_OFFSET ) ) ) ;
if ( ( Key . UnicodeChar | UPPER_LOWER_CASE_OFFSET ) = = ( DiscardChange | UPPER_LOWER_CASE_OFFSET ) ) {
gUserInput - > Action = BROWSER_ACTION_DISCARD ;
} else {
gUserInput - > Action = BROWSER_ACTION_GOTO ;
}
break ;
default :
if ( TimeOut = = 0 ) {
do {
CreateDialog ( & Key , gEmptyString , ErrorInfo , gPressEnter , gEmptyString , NULL ) ;
} while ( Key . UnicodeChar ! = CHAR_CARRIAGE_RETURN ) ;
} else {
Status = gBS - > CreateEvent ( EVT_NOTIFY_WAIT , TPL_CALLBACK , EmptyEventProcess , NULL , & TimeOutEvent ) ;
2020-04-23 11:08:10 +02:00
ASSERT_EFI_ERROR ( Status ) ;
2019-09-03 11:58:42 +02:00
EventContext . SyncEvent = TimeOutEvent ;
EventContext . TimeOut = & TimeOut ;
EventContext . ErrorInfo = ErrorInfo ;
Status = gBS - > CreateEvent ( EVT_TIMER | EVT_NOTIFY_SIGNAL , TPL_CALLBACK , RefreshTimeOutProcess , & EventContext , & RefreshIntervalEvent ) ;
2020-04-23 11:08:10 +02:00
ASSERT_EFI_ERROR ( Status ) ;
2019-09-03 11:58:42 +02:00
//
// Show the dialog first to avoid long time not reaction.
//
gBS - > SignalEvent ( RefreshIntervalEvent ) ;
Status = gBS - > SetTimer ( RefreshIntervalEvent , TimerPeriodic , ONE_SECOND ) ;
2020-04-23 11:08:10 +02:00
ASSERT_EFI_ERROR ( Status ) ;
2019-09-03 11:58:42 +02:00
while ( TRUE ) {
Status = gST - > ConIn - > ReadKeyStroke ( gST - > ConIn , & Key ) ;
2020-04-23 11:08:10 +02:00
if ( ! EFI_ERROR ( Status ) & & Key . UnicodeChar = = CHAR_CARRIAGE_RETURN ) {
2019-09-03 11:58:42 +02:00
break ;
}
if ( Status ! = EFI_NOT_READY ) {
continue ;
}
WaitList [ 0 ] = TimeOutEvent ;
WaitList [ 1 ] = gST - > ConIn - > WaitForKey ;
Status = gBS - > WaitForEvent ( 2 , WaitList , & Index ) ;
2020-04-23 11:08:10 +02:00
ASSERT_EFI_ERROR ( Status ) ;
2019-09-03 11:58:42 +02:00
if ( Index = = 0 ) {
//
// Timeout occur, close the hoot time out event.
//
break ;
}
}
gBS - > CloseEvent ( TimeOutEvent ) ;
gBS - > CloseEvent ( RefreshIntervalEvent ) ;
}
break ;
}
if ( StringToken ! = 0 ) {
2020-04-23 11:08:10 +02:00
FreePool ( ErrorInfo ) ;
2019-09-03 11:58:42 +02:00
}
}
/**
Display one form , and return user input .
@ param FormData Form Data to be shown .
@ param UserInputData User input data .
@ retval EFI_SUCCESS 1.F orm 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 ( gFormData - > BrowserStatus ! = BROWSER_SUCCESS ) {
//
// gFormData->BrowserStatus != BROWSER_SUCCESS, means only need to print the error info, return here.
//
return EFI_SUCCESS ;
}
Status = DisplayPageFrame ( FormData , & gStatementDimensions ) ;
2020-04-23 11:08:10 +02:00
if ( EFI_ERROR ( Status ) ) {
2019-09-03 11:58:42 +02:00
return Status ;
}
//
// Global Widths should be initialized before any MenuOption creation
// or the GetWidth() used in UiAddMenuOption() will return incorrect value.
//
//
// Left right
// |<-.->|<-.........->|<- .........->|<-...........->|
// Skip Prompt Option Help
//
gOptionBlockWidth = ( CHAR16 ) ( ( gStatementDimensions . RightColumn - gStatementDimensions . LeftColumn ) / 3 ) + 1 ;
gHelpBlockWidth = ( CHAR16 ) ( gOptionBlockWidth - 1 - LEFT_SKIPPED_COLUMNS ) ;
gPromptBlockWidth = ( CHAR16 ) ( gStatementDimensions . RightColumn - gStatementDimensions . LeftColumn - 2 * ( gOptionBlockWidth - 1 ) - 1 ) ;
ConvertStatementToMenu ( ) ;
//
// 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 ;
//
//Free the Ui menu option list.
//
FreeMenuOptionData ( & gMenuOption ) ;
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
) ;
2020-04-23 11:08:10 +02:00
ASSERT_EFI_ERROR ( Status ) ;
2019-09-03 11:58:42 +02:00
//
// Install HII Popup Protocol.
//
Status = gBS - > InstallProtocolInterface (
& mPrivateData . Handle ,
& gEfiHiiPopupProtocolGuid ,
EFI_NATIVE_INTERFACE ,
& mPrivateData . HiiPopup
) ;
2020-04-23 11:08:10 +02:00
ASSERT_EFI_ERROR ( Status ) ;
2019-09-03 11:58:42 +02:00
InitializeDisplayStrings ( ) ;
ZeroMem ( & gHighligthMenuInfo , sizeof ( gHighligthMenuInfo ) ) ;
ZeroMem ( & gOldFormEntry , sizeof ( gOldFormEntry ) ) ;
//
// Use BrowserEx2 protocol to register HotKey.
//
Status = gBS - > LocateProtocol ( & gEdkiiFormBrowserEx2ProtocolGuid , NULL , ( VOID * * ) & FormBrowserEx2 ) ;
2020-04-23 11:08:10 +02:00
if ( ! EFI_ERROR ( Status ) ) {
2019-09-03 11:58:42 +02:00
//
// 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 ) ;
2020-04-23 11:08:10 +02:00
FreePool ( NewString ) ;
2019-09-03 11:58:42 +02:00
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 ) ;
2020-04-23 11:08:10 +02:00
FreePool ( NewString ) ;
2019-09-03 11:58:42 +02:00
}
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 ( ) ;
if ( gHighligthMenuInfo . HLTOpCode ! = NULL ) {
2020-04-23 11:08:10 +02:00
FreePool ( gHighligthMenuInfo . HLTOpCode ) ;
2019-09-03 11:58:42 +02:00
}
if ( gHighligthMenuInfo . TOSOpCode ! = NULL ) {
2020-04-23 11:08:10 +02:00
FreePool ( gHighligthMenuInfo . TOSOpCode ) ;
2019-09-03 11:58:42 +02:00
}
return EFI_SUCCESS ;
}