audk/MdeModulePkg/Universal/SetupBrowserDxe/Presentation.c

1169 lines
36 KiB
C

/** @file
Utility functions for UI presentation.
Copyright (c) 2004 - 2010, Intel Corporation
All rights reserved. This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License
which accompanies this distribution. The full text of the license may be found at
http://opensource.org/licenses/bsd-license.php
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
**/
#include "Setup.h"
BOOLEAN mHiiPackageListUpdated;
UI_MENU_SELECTION *gCurrentSelection;
/**
Clear retangle with specified text attribute.
@param LeftColumn Left column of retangle.
@param RightColumn Right column of retangle.
@param TopRow Start row of retangle.
@param BottomRow End row of retangle.
@param TextAttribute The character foreground and background.
**/
VOID
ClearLines (
IN UINTN LeftColumn,
IN UINTN RightColumn,
IN UINTN TopRow,
IN UINTN BottomRow,
IN UINTN TextAttribute
)
{
CHAR16 *Buffer;
UINTN Row;
//
// For now, allocate an arbitrarily long buffer
//
Buffer = AllocateZeroPool (0x10000);
ASSERT (Buffer != NULL);
//
// Set foreground and background as defined
//
gST->ConOut->SetAttribute (gST->ConOut, TextAttribute);
//
// Much faster to buffer the long string instead of print it a character at a time
//
SetUnicodeMem (Buffer, RightColumn - LeftColumn, L' ');
//
// Clear the desired area with the appropriate foreground/background
//
for (Row = TopRow; Row <= BottomRow; Row++) {
PrintStringAt (LeftColumn, Row, Buffer);
}
gST->ConOut->SetCursorPosition (gST->ConOut, LeftColumn, TopRow);
FreePool (Buffer);
return ;
}
/**
Concatenate a narrow string to another string.
@param Destination The destination string.
@param Source The source string. The string to be concatenated.
to the end of Destination.
**/
VOID
NewStrCat (
IN OUT CHAR16 *Destination,
IN CHAR16 *Source
)
{
UINTN Length;
for (Length = 0; Destination[Length] != 0; Length++)
;
//
// We now have the length of the original string
// We can safely assume for now that we are concatenating a narrow value to this string.
// For instance, the string is "XYZ" and cat'ing ">"
// If this assumption changes, we need to make this routine a bit more complex
//
Destination[Length] = NARROW_CHAR;
Length++;
StrCpy (Destination + Length, Source);
}
/**
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.
@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;
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);
}
/**
This function displays the page frame.
**/
VOID
DisplayPageFrame (
VOID
)
{
UINTN Index;
UINT8 Line;
UINT8 Alignment;
CHAR16 Character;
CHAR16 *Buffer;
CHAR16 *StrFrontPageBanner;
UINTN Row;
EFI_SCREEN_DESCRIPTOR LocalScreen;
UINT8 RowIdx;
UINT8 ColumnIdx;
ZeroMem (&LocalScreen, sizeof (EFI_SCREEN_DESCRIPTOR));
gST->ConOut->QueryMode (gST->ConOut, gST->ConOut->Mode->Mode, &LocalScreen.RightColumn, &LocalScreen.BottomRow);
ClearLines (0, LocalScreen.RightColumn, 0, LocalScreen.BottomRow, KEYHELP_BACKGROUND);
CopyMem (&LocalScreen, &gScreenDimensions, sizeof (EFI_SCREEN_DESCRIPTOR));
//
// For now, allocate an arbitrarily long buffer
//
Buffer = AllocateZeroPool (0x10000);
ASSERT (Buffer != NULL);
Character = BOXDRAW_HORIZONTAL;
for (Index = 0; Index + 2 < (LocalScreen.RightColumn - LocalScreen.LeftColumn); Index++) {
Buffer[Index] = Character;
}
if ((gClassOfVfr & FORMSET_CLASS_FRONT_PAGE) == FORMSET_CLASS_FRONT_PAGE) {
//
// ClearLines(0, LocalScreen.RightColumn, 0, BANNER_HEIGHT-1, BANNER_TEXT | BANNER_BACKGROUND);
//
ClearLines (
LocalScreen.LeftColumn,
LocalScreen.RightColumn,
LocalScreen.TopRow,
FRONT_PAGE_HEADER_HEIGHT - 1 + LocalScreen.TopRow,
BANNER_TEXT | BANNER_BACKGROUND
);
//
// for (Line = 0; Line < BANNER_HEIGHT; Line++) {
//
for (Line = (UINT8) LocalScreen.TopRow; Line < BANNER_HEIGHT + (UINT8) LocalScreen.TopRow; Line++) {
//
// for (Alignment = 0; Alignment < BANNER_COLUMNS; Alignment++) {
//
for (Alignment = (UINT8) LocalScreen.LeftColumn;
Alignment < BANNER_COLUMNS + (UINT8) LocalScreen.LeftColumn;
Alignment++
) {
RowIdx = (UINT8) (Line - (UINT8) LocalScreen.TopRow);
ColumnIdx = (UINT8) (Alignment - (UINT8) LocalScreen.LeftColumn);
ASSERT (RowIdx < BANNER_HEIGHT);
ASSERT (ColumnIdx < BANNER_COLUMNS);
if (gBannerData->Banner[RowIdx][ColumnIdx] != 0x0000) {
StrFrontPageBanner = GetToken (
gBannerData->Banner[RowIdx][ColumnIdx],
gFrontPageHandle
);
} else {
continue;
}
switch (Alignment - LocalScreen.LeftColumn) {
case 0:
//
// Handle left column
//
PrintStringAt (LocalScreen.LeftColumn, Line, StrFrontPageBanner);
break;
case 1:
//
// Handle center column
//
PrintStringAt (
LocalScreen.LeftColumn + (LocalScreen.RightColumn - LocalScreen.LeftColumn) / 3,
Line,
StrFrontPageBanner
);
break;
case 2:
//
// Handle right column
//
PrintStringAt (
LocalScreen.LeftColumn + (LocalScreen.RightColumn - LocalScreen.LeftColumn) * 2 / 3,
Line,
StrFrontPageBanner
);
break;
}
FreePool (StrFrontPageBanner);
}
}
}
ClearLines (
LocalScreen.LeftColumn,
LocalScreen.RightColumn,
LocalScreen.BottomRow - STATUS_BAR_HEIGHT - FOOTER_HEIGHT,
LocalScreen.BottomRow - STATUS_BAR_HEIGHT - 1,
KEYHELP_TEXT | KEYHELP_BACKGROUND
);
if ((gClassOfVfr & FORMSET_CLASS_FRONT_PAGE) != FORMSET_CLASS_FRONT_PAGE) {
ClearLines (
LocalScreen.LeftColumn,
LocalScreen.RightColumn,
LocalScreen.TopRow,
LocalScreen.TopRow + NONE_FRONT_PAGE_HEADER_HEIGHT - 1,
TITLE_TEXT | TITLE_BACKGROUND
);
//
// Print Top border line
// +------------------------------------------------------------------------------+
// ? ?
// +------------------------------------------------------------------------------+
//
Character = BOXDRAW_DOWN_RIGHT;
PrintChar (Character);
PrintString (Buffer);
Character = BOXDRAW_DOWN_LEFT;
PrintChar (Character);
Character = BOXDRAW_VERTICAL;
for (Row = LocalScreen.TopRow + 1; Row <= LocalScreen.TopRow + NONE_FRONT_PAGE_HEADER_HEIGHT - 2; Row++) {
PrintCharAt (LocalScreen.LeftColumn, Row, Character);
PrintCharAt (LocalScreen.RightColumn - 1, Row, Character);
}
Character = BOXDRAW_UP_RIGHT;
PrintCharAt (LocalScreen.LeftColumn, LocalScreen.TopRow + NONE_FRONT_PAGE_HEADER_HEIGHT - 1, Character);
PrintString (Buffer);
Character = BOXDRAW_UP_LEFT;
PrintChar (Character);
if ((gClassOfVfr & FORMSET_CLASS_PLATFORM_SETUP) == FORMSET_CLASS_PLATFORM_SETUP) {
//
// Print Bottom border line
// +------------------------------------------------------------------------------+
// ? ?
// +------------------------------------------------------------------------------+
//
Character = BOXDRAW_DOWN_RIGHT;
PrintCharAt (LocalScreen.LeftColumn, LocalScreen.BottomRow - STATUS_BAR_HEIGHT - FOOTER_HEIGHT, Character);
PrintString (Buffer);
Character = BOXDRAW_DOWN_LEFT;
PrintChar (Character);
Character = BOXDRAW_VERTICAL;
for (Row = LocalScreen.BottomRow - STATUS_BAR_HEIGHT - FOOTER_HEIGHT + 1;
Row <= LocalScreen.BottomRow - STATUS_BAR_HEIGHT - 2;
Row++
) {
PrintCharAt (LocalScreen.LeftColumn, Row, Character);
PrintCharAt (LocalScreen.RightColumn - 1, Row, Character);
}
Character = BOXDRAW_UP_RIGHT;
PrintCharAt (LocalScreen.LeftColumn, LocalScreen.BottomRow - STATUS_BAR_HEIGHT - 1, Character);
PrintString (Buffer);
Character = BOXDRAW_UP_LEFT;
PrintChar (Character);
}
}
FreePool (Buffer);
}
/**
Evaluate all expressions in a Form.
@param FormSet FormSet this Form belongs to.
@param Form The Form.
@retval EFI_SUCCESS The expression evaluated successfuly
**/
EFI_STATUS
EvaluateFormExpressions (
IN FORM_BROWSER_FORMSET *FormSet,
IN FORM_BROWSER_FORM *Form
)
{
EFI_STATUS Status;
LIST_ENTRY *Link;
FORM_EXPRESSION *Expression;
Link = GetFirstNode (&Form->ExpressionListHead);
while (!IsNull (&Form->ExpressionListHead, Link)) {
Expression = FORM_EXPRESSION_FROM_LINK (Link);
Link = GetNextNode (&Form->ExpressionListHead, Link);
if (Expression->Type == EFI_HII_EXPRESSION_INCONSISTENT_IF ||
Expression->Type == EFI_HII_EXPRESSION_NO_SUBMIT_IF ||
Expression->Type == EFI_HII_EXPRESSION_WRITE ||
(Expression->Type == EFI_HII_EXPRESSION_READ && Form->FormType != STANDARD_MAP_FORM_TYPE)) {
//
// Postpone Form validation to Question editing or Form submitting or Question Write or Question Read for nonstandard form.
//
continue;
}
Status = EvaluateExpression (FormSet, Form, Expression);
if (EFI_ERROR (Status)) {
return Status;
}
}
return EFI_SUCCESS;
}
/*
+------------------------------------------------------------------------------+
? Setup Page ?
+------------------------------------------------------------------------------+
+------------------------------------------------------------------------------+
?F1=Scroll Help F9=Reset to Defaults F10=Save and Exit ?
| ^"=Move Highlight <Spacebar> Toggles Checkbox Esc=Discard Changes |
+------------------------------------------------------------------------------+
*/
/**
Display form and wait for user to select one menu option, then return it.
@param Selection On input, Selection tell setup browser the information
about the Selection, form and formset to be displayed.
On output, Selection return the screen item that is selected
by user.
@retval EFI_SUCESSS This function always return successfully for now.
**/
EFI_STATUS
DisplayForm (
IN OUT UI_MENU_SELECTION *Selection
)
{
CHAR16 *StringPtr;
UINT16 MenuItemCount;
EFI_HII_HANDLE Handle;
BOOLEAN Suppress;
EFI_SCREEN_DESCRIPTOR LocalScreen;
UINT16 Width;
UINTN ArrayEntry;
CHAR16 *OutputString;
LIST_ENTRY *Link;
FORM_BROWSER_STATEMENT *Statement;
UINT16 NumberOfLines;
EFI_STATUS Status;
UI_MENU_OPTION *MenuOption;
Handle = Selection->Handle;
MenuItemCount = 0;
ArrayEntry = 0;
OutputString = NULL;
UiInitMenu ();
CopyMem (&LocalScreen, &gScreenDimensions, sizeof (EFI_SCREEN_DESCRIPTOR));
StringPtr = GetToken (Selection->Form->FormTitle, Handle);
if ((gClassOfVfr & FORMSET_CLASS_FRONT_PAGE) != FORMSET_CLASS_FRONT_PAGE) {
gST->ConOut->SetAttribute (gST->ConOut, TITLE_TEXT | TITLE_BACKGROUND);
PrintStringAt (
(LocalScreen.RightColumn + LocalScreen.LeftColumn - GetStringWidth (StringPtr) / 2) / 2,
LocalScreen.TopRow + 1,
StringPtr
);
}
//
// Remove Buffer allocated for StringPtr after it has been used.
//
FreePool (StringPtr);
//
// Evaluate all the Expressions in this Form
//
Status = EvaluateFormExpressions (Selection->FormSet, Selection->Form);
if (EFI_ERROR (Status)) {
return Status;
}
Selection->FormEditable = FALSE;
Link = GetFirstNode (&Selection->Form->StatementListHead);
while (!IsNull (&Selection->Form->StatementListHead, Link)) {
Statement = FORM_BROWSER_STATEMENT_FROM_LINK (Link);
if (Statement->SuppressExpression != NULL) {
Suppress = Statement->SuppressExpression->Result.Value.b;
} else {
Suppress = FALSE;
}
if (Statement->DisableExpression != NULL) {
Suppress = (BOOLEAN) (Suppress || Statement->DisableExpression->Result.Value.b);
}
if (!Suppress) {
StringPtr = GetToken (Statement->Prompt, Handle);
Width = GetWidth (Statement, Handle);
NumberOfLines = 1;
ArrayEntry = 0;
for (; GetLineByWidth (StringPtr, Width, &ArrayEntry, &OutputString) != 0x0000;) {
//
// If there is more string to process print on the next row and increment the Skip value
//
if (StrLen (&StringPtr[ArrayEntry]) != 0) {
NumberOfLines++;
}
FreePool (OutputString);
}
//
// We are NOT!! removing this StringPtr buffer via FreePool since it is being used in the menuoptions, we will do
// it in UiFreeMenu.
//
MenuOption = UiAddMenuOption (StringPtr, Selection->Handle, Statement, NumberOfLines, MenuItemCount);
MenuItemCount++;
if (MenuOption->IsQuestion && !MenuOption->ReadOnly) {
//
// At least one item is not readonly, this Form is considered as editable
//
Selection->FormEditable = TRUE;
}
}
Link = GetNextNode (&Selection->Form->StatementListHead, Link);
}
Status = UiDisplayMenu (Selection);
UiFreeMenu ();
return Status;
}
/**
Initialize the HII String Token to the correct values.
**/
VOID
InitializeBrowserStrings (
VOID
)
{
gFunctionNineString = GetToken (STRING_TOKEN (FUNCTION_NINE_STRING), gHiiHandle);
gFunctionTenString = GetToken (STRING_TOKEN (FUNCTION_TEN_STRING), gHiiHandle);
gEnterString = GetToken (STRING_TOKEN (ENTER_STRING), gHiiHandle);
gEnterCommitString = GetToken (STRING_TOKEN (ENTER_COMMIT_STRING), gHiiHandle);
gEnterEscapeString = GetToken (STRING_TOKEN (ENTER_ESCAPE_STRING), gHiiHandle);
gEscapeString = GetToken (STRING_TOKEN (ESCAPE_STRING), gHiiHandle);
gSaveFailed = GetToken (STRING_TOKEN (SAVE_FAILED), gHiiHandle);
gMoveHighlight = GetToken (STRING_TOKEN (MOVE_HIGHLIGHT), gHiiHandle);
gMakeSelection = GetToken (STRING_TOKEN (MAKE_SELECTION), gHiiHandle);
gDecNumericInput = GetToken (STRING_TOKEN (DEC_NUMERIC_INPUT), gHiiHandle);
gHexNumericInput = GetToken (STRING_TOKEN (HEX_NUMERIC_INPUT), gHiiHandle);
gToggleCheckBox = GetToken (STRING_TOKEN (TOGGLE_CHECK_BOX), gHiiHandle);
gPromptForData = GetToken (STRING_TOKEN (PROMPT_FOR_DATA), gHiiHandle);
gPromptForPassword = GetToken (STRING_TOKEN (PROMPT_FOR_PASSWORD), gHiiHandle);
gPromptForNewPassword = GetToken (STRING_TOKEN (PROMPT_FOR_NEW_PASSWORD), gHiiHandle);
gConfirmPassword = GetToken (STRING_TOKEN (CONFIRM_PASSWORD), gHiiHandle);
gConfirmError = GetToken (STRING_TOKEN (CONFIRM_ERROR), gHiiHandle);
gPassowordInvalid = GetToken (STRING_TOKEN (PASSWORD_INVALID), gHiiHandle);
gPressEnter = GetToken (STRING_TOKEN (PRESS_ENTER), gHiiHandle);
gEmptyString = GetToken (STRING_TOKEN (EMPTY_STRING), gHiiHandle);
gAreYouSure = GetToken (STRING_TOKEN (ARE_YOU_SURE), gHiiHandle);
gYesResponse = GetToken (STRING_TOKEN (ARE_YOU_SURE_YES), gHiiHandle);
gNoResponse = GetToken (STRING_TOKEN (ARE_YOU_SURE_NO), gHiiHandle);
gMiniString = GetToken (STRING_TOKEN (MINI_STRING), gHiiHandle);
gPlusString = GetToken (STRING_TOKEN (PLUS_STRING), gHiiHandle);
gMinusString = GetToken (STRING_TOKEN (MINUS_STRING), gHiiHandle);
gAdjustNumber = GetToken (STRING_TOKEN (ADJUST_NUMBER), gHiiHandle);
gSaveChanges = GetToken (STRING_TOKEN (SAVE_CHANGES), gHiiHandle);
gOptionMismatch = GetToken (STRING_TOKEN (OPTION_MISMATCH), gHiiHandle);
gFormSuppress = GetToken (STRING_TOKEN (FORM_SUPPRESSED), gHiiHandle);
return ;
}
/**
Free up the resource allocated for all strings required
by Setup Browser.
**/
VOID
FreeBrowserStrings (
VOID
)
{
FreePool (gFunctionNineString);
FreePool (gFunctionTenString);
FreePool (gEnterString);
FreePool (gEnterCommitString);
FreePool (gEnterEscapeString);
FreePool (gEscapeString);
FreePool (gMoveHighlight);
FreePool (gMakeSelection);
FreePool (gDecNumericInput);
FreePool (gHexNumericInput);
FreePool (gToggleCheckBox);
FreePool (gPromptForData);
FreePool (gPromptForPassword);
FreePool (gPromptForNewPassword);
FreePool (gConfirmPassword);
FreePool (gPassowordInvalid);
FreePool (gConfirmError);
FreePool (gPressEnter);
FreePool (gEmptyString);
FreePool (gAreYouSure);
FreePool (gYesResponse);
FreePool (gNoResponse);
FreePool (gMiniString);
FreePool (gPlusString);
FreePool (gMinusString);
FreePool (gAdjustNumber);
FreePool (gSaveChanges);
FreePool (gOptionMismatch);
FreePool (gFormSuppress);
return ;
}
/**
Update key's help imformation.
@param Selection Tell setup browser the information about the Selection
@param MenuOption The Menu option
@param Selected Whether or not a tag be selected
**/
VOID
UpdateKeyHelp (
IN UI_MENU_SELECTION *Selection,
IN UI_MENU_OPTION *MenuOption,
IN BOOLEAN Selected
)
{
UINTN SecCol;
UINTN ThdCol;
UINTN LeftColumnOfHelp;
UINTN RightColumnOfHelp;
UINTN TopRowOfHelp;
UINTN BottomRowOfHelp;
UINTN StartColumnOfHelp;
EFI_SCREEN_DESCRIPTOR LocalScreen;
FORM_BROWSER_STATEMENT *Statement;
CopyMem (&LocalScreen, &gScreenDimensions, sizeof (EFI_SCREEN_DESCRIPTOR));
SecCol = LocalScreen.LeftColumn + (LocalScreen.RightColumn - LocalScreen.LeftColumn) / 3;
ThdCol = LocalScreen.LeftColumn + (LocalScreen.RightColumn - LocalScreen.LeftColumn) * 2 / 3;
StartColumnOfHelp = LocalScreen.LeftColumn + 2;
LeftColumnOfHelp = LocalScreen.LeftColumn + 1;
RightColumnOfHelp = LocalScreen.RightColumn - 2;
TopRowOfHelp = LocalScreen.BottomRow - 4;
BottomRowOfHelp = LocalScreen.BottomRow - 3;
gST->ConOut->SetAttribute (gST->ConOut, KEYHELP_TEXT | KEYHELP_BACKGROUND);
Statement = MenuOption->ThisTag;
switch (Statement->Operand) {
case EFI_IFR_ORDERED_LIST_OP:
case EFI_IFR_ONE_OF_OP:
case EFI_IFR_NUMERIC_OP:
case EFI_IFR_TIME_OP:
case EFI_IFR_DATE_OP:
ClearLines (LeftColumnOfHelp, RightColumnOfHelp, TopRowOfHelp, BottomRowOfHelp, KEYHELP_TEXT | KEYHELP_BACKGROUND);
if (!Selected) {
if ((gClassOfVfr & FORMSET_CLASS_PLATFORM_SETUP) == FORMSET_CLASS_PLATFORM_SETUP) {
if (Selection->FormEditable) {
PrintStringAt (SecCol, TopRowOfHelp, gFunctionNineString);
PrintStringAt (ThdCol, TopRowOfHelp, gFunctionTenString);
}
PrintStringAt (ThdCol, BottomRowOfHelp, gEscapeString);
}
if ((Statement->Operand == EFI_IFR_DATE_OP) ||
(Statement->Operand == EFI_IFR_TIME_OP)) {
PrintAt (
StartColumnOfHelp,
BottomRowOfHelp,
L"%c%c%c%c%s",
ARROW_UP,
ARROW_DOWN,
ARROW_RIGHT,
ARROW_LEFT,
gMoveHighlight
);
PrintStringAt (SecCol, BottomRowOfHelp, gAdjustNumber);
} else {
PrintAt (StartColumnOfHelp, BottomRowOfHelp, L"%c%c%s", ARROW_UP, ARROW_DOWN, gMoveHighlight);
if (Statement->Operand == EFI_IFR_NUMERIC_OP && Statement->Step != 0) {
PrintStringAt (SecCol, BottomRowOfHelp, gAdjustNumber);
} else {
PrintStringAt (SecCol, BottomRowOfHelp, gEnterString);
}
}
} else {
PrintStringAt (SecCol, BottomRowOfHelp, gEnterCommitString);
//
// If it is a selected numeric with manual input, display different message
//
if ((Statement->Operand == EFI_IFR_NUMERIC_OP) && (Statement->Step == 0)) {
PrintStringAt (
SecCol,
TopRowOfHelp,
((Statement->Flags & EFI_IFR_DISPLAY_UINT_HEX) == EFI_IFR_DISPLAY_UINT_HEX) ? gHexNumericInput : gDecNumericInput
);
} else if (Statement->Operand != EFI_IFR_ORDERED_LIST_OP) {
PrintAt (StartColumnOfHelp, BottomRowOfHelp, L"%c%c%s", ARROW_UP, ARROW_DOWN, gMoveHighlight);
}
if (Statement->Operand == EFI_IFR_ORDERED_LIST_OP) {
PrintStringAt (StartColumnOfHelp, TopRowOfHelp, gPlusString);
PrintStringAt (ThdCol, TopRowOfHelp, gMinusString);
}
PrintStringAt (ThdCol, BottomRowOfHelp, gEnterEscapeString);
}
break;
case EFI_IFR_CHECKBOX_OP:
ClearLines (LeftColumnOfHelp, RightColumnOfHelp, TopRowOfHelp, BottomRowOfHelp, KEYHELP_TEXT | KEYHELP_BACKGROUND);
if ((gClassOfVfr & FORMSET_CLASS_PLATFORM_SETUP) == FORMSET_CLASS_PLATFORM_SETUP) {
if (Selection->FormEditable) {
PrintStringAt (SecCol, TopRowOfHelp, gFunctionNineString);
PrintStringAt (ThdCol, TopRowOfHelp, gFunctionTenString);
}
PrintStringAt (ThdCol, BottomRowOfHelp, gEscapeString);
}
PrintAt (StartColumnOfHelp, BottomRowOfHelp, L"%c%c%s", ARROW_UP, ARROW_DOWN, gMoveHighlight);
PrintStringAt (SecCol, BottomRowOfHelp, gToggleCheckBox);
break;
case EFI_IFR_REF_OP:
case EFI_IFR_PASSWORD_OP:
case EFI_IFR_STRING_OP:
case EFI_IFR_TEXT_OP:
case EFI_IFR_ACTION_OP:
case EFI_IFR_RESET_BUTTON_OP:
ClearLines (LeftColumnOfHelp, RightColumnOfHelp, TopRowOfHelp, BottomRowOfHelp, KEYHELP_TEXT | KEYHELP_BACKGROUND);
if (!Selected) {
if ((gClassOfVfr & FORMSET_CLASS_PLATFORM_SETUP) == FORMSET_CLASS_PLATFORM_SETUP) {
if (Selection->FormEditable) {
PrintStringAt (SecCol, TopRowOfHelp, gFunctionNineString);
PrintStringAt (ThdCol, TopRowOfHelp, gFunctionTenString);
}
PrintStringAt (ThdCol, BottomRowOfHelp, gEscapeString);
}
PrintAt (StartColumnOfHelp, BottomRowOfHelp, L"%c%c%s", ARROW_UP, ARROW_DOWN, gMoveHighlight);
if (Statement->Operand != EFI_IFR_TEXT_OP) {
PrintStringAt (SecCol, BottomRowOfHelp, gEnterString);
}
} else {
if (Statement->Operand != EFI_IFR_REF_OP) {
PrintStringAt (
(LocalScreen.RightColumn - GetStringWidth (gEnterCommitString) / 2) / 2,
BottomRowOfHelp,
gEnterCommitString
);
PrintStringAt (ThdCol, BottomRowOfHelp, gEnterEscapeString);
}
}
break;
default:
break;
}
}
/**
Functions which are registered to receive notification of
database events have this prototype. The actual event is encoded
in NotifyType. The following table describes how PackageType,
PackageGuid, Handle, and Package are used for each of the
notification types.
@param PackageType Package type of the notification.
@param PackageGuid If PackageType is
EFI_HII_PACKAGE_TYPE_GUID, then this is
the pointer to the GUID from the Guid
field of EFI_HII_PACKAGE_GUID_HEADER.
Otherwise, it must be NULL.
@param Package Points to the package referred to by the
notification Handle The handle of the package
list which contains the specified package.
@param Handle The HII handle.
@param NotifyType The type of change concerning the
database. See
EFI_HII_DATABASE_NOTIFY_TYPE.
**/
EFI_STATUS
EFIAPI
FormUpdateNotify (
IN UINT8 PackageType,
IN CONST EFI_GUID *PackageGuid,
IN CONST EFI_HII_PACKAGE_HEADER *Package,
IN EFI_HII_HANDLE Handle,
IN EFI_HII_DATABASE_NOTIFY_TYPE NotifyType
)
{
mHiiPackageListUpdated = TRUE;
return EFI_SUCCESS;
}
/**
The worker function that send the displays to the screen. On output,
the selection made by user is returned.
@param Selection On input, Selection tell setup browser the information
about the Selection, form and formset to be displayed.
On output, Selection return the screen item that is selected
by user.
@retval EFI_SUCCESS The page is displayed successfully.
@return Other value if the page failed to be diplayed.
**/
EFI_STATUS
SetupBrowser (
IN OUT UI_MENU_SELECTION *Selection
)
{
EFI_STATUS Status;
LIST_ENTRY *Link;
EFI_BROWSER_ACTION_REQUEST ActionRequest;
EFI_HANDLE NotifyHandle;
EFI_HII_VALUE *HiiValue;
EFI_IFR_TYPE_VALUE *TypeValue;
FORM_BROWSER_STATEMENT *Statement;
EFI_HII_CONFIG_ACCESS_PROTOCOL *ConfigAccess;
FORM_BROWSER_FORMSET *FormSet;
EFI_INPUT_KEY Key;
gMenuRefreshHead = NULL;
gResetRequired = FALSE;
FormSet = Selection->FormSet;
//
// Register notify for Form package update
//
Status = mHiiDatabase->RegisterPackageNotify (
mHiiDatabase,
EFI_HII_PACKAGE_FORMS,
NULL,
FormUpdateNotify,
EFI_HII_DATABASE_NOTIFY_REMOVE_PACK,
&NotifyHandle
);
if (EFI_ERROR (Status)) {
return Status;
}
//
// Before display the formset, invoke ConfigAccess.Callback() with EFI_BROWSER_ACTION_FORM_OPEN
//
ConfigAccess = Selection->FormSet->ConfigAccess;
if ((ConfigAccess != NULL) && (Selection->Action != UI_ACTION_REFRESH_FORMSET)) {
ActionRequest = EFI_BROWSER_ACTION_REQUEST_NONE;
mHiiPackageListUpdated = FALSE;
Status = ConfigAccess->Callback (
ConfigAccess,
EFI_BROWSER_ACTION_FORM_OPEN,
0,
EFI_IFR_TYPE_UNDEFINED,
NULL,
&ActionRequest
);
if (!EFI_ERROR (Status)) {
switch (ActionRequest) {
case EFI_BROWSER_ACTION_REQUEST_RESET:
gResetRequired = TRUE;
break;
case EFI_BROWSER_ACTION_REQUEST_SUBMIT:
//
// Till now there is no uncommitted data, so ignore this request
//
break;
case EFI_BROWSER_ACTION_REQUEST_EXIT:
Selection->Action = UI_ACTION_EXIT;
break;
default:
break;
}
}
if (mHiiPackageListUpdated) {
//
// IFR is updated during callback, force to reparse the IFR binary
//
mHiiPackageListUpdated = FALSE;
Selection->Action = UI_ACTION_REFRESH_FORMSET;
goto Done;
}
}
//
// Initialize current settings of Questions in this FormSet
//
Status = InitializeCurrentSetting (Selection->FormSet);
if (EFI_ERROR (Status)) {
Selection->Action = UI_ACTION_EXIT;
goto Done;
}
do {
//
// Initialize Selection->Form
//
if (Selection->FormId == 0) {
//
// Zero FormId indicates display the first Form in a FormSet
//
Link = GetFirstNode (&Selection->FormSet->FormListHead);
Selection->Form = FORM_BROWSER_FORM_FROM_LINK (Link);
Selection->FormId = Selection->Form->FormId;
} else {
Selection->Form = IdToForm (Selection->FormSet, Selection->FormId);
}
if (Selection->Form == NULL) {
//
// No Form to display
//
return EFI_NOT_FOUND;
}
//
// Check Form is suppressed.
//
if (Selection->Form->SuppressExpression != NULL) {
Status = EvaluateExpression (Selection->FormSet, Selection->Form, Selection->Form->SuppressExpression);
if (EFI_ERROR (Status)) {
return Status;
}
if (Selection->Form->SuppressExpression->Result.Value.b) {
//
// Form is suppressed.
//
do {
CreateDialog (4, TRUE, 0, NULL, &Key, gEmptyString, gFormSuppress, gPressEnter, gEmptyString);
} while (Key.UnicodeChar != CHAR_CARRIAGE_RETURN);
return EFI_NOT_FOUND;
}
}
//
// Reset FormPackage update flag
//
mHiiPackageListUpdated = FALSE;
//
// Load Questions' Value for display
//
Status = LoadFormSetConfig (Selection, Selection->FormSet);
if (EFI_ERROR (Status)) {
return Status;
}
//
// IFR is updated during callback of read value, force to reparse the IFR binary
//
if (mHiiPackageListUpdated) {
Selection->Action = UI_ACTION_REFRESH_FORMSET;
mHiiPackageListUpdated = FALSE;
goto Done;
}
//
// Displays the Header and Footer borders
//
DisplayPageFrame ();
//
// Display form
//
Status = DisplayForm (Selection);
if (EFI_ERROR (Status)) {
return Status;
}
//
// Check Selected Statement (if press ESC, Selection->Statement will be NULL)
//
Statement = Selection->Statement;
if (Statement != NULL) {
if ((Statement->QuestionFlags & EFI_IFR_FLAG_RESET_REQUIRED) == EFI_IFR_FLAG_RESET_REQUIRED) {
gResetRequired = TRUE;
}
//
// Reset FormPackage update flag
//
mHiiPackageListUpdated = FALSE;
if (((Statement->QuestionFlags & EFI_IFR_FLAG_CALLBACK) == EFI_IFR_FLAG_CALLBACK) && (Statement->Operand != EFI_IFR_PASSWORD_OP)) {
ActionRequest = EFI_BROWSER_ACTION_REQUEST_NONE;
if (ConfigAccess == NULL) {
return EFI_UNSUPPORTED;
}
HiiValue = &Statement->HiiValue;
TypeValue = &HiiValue->Value;
if (HiiValue->Type == EFI_IFR_TYPE_STRING) {
//
// Create String in HII database for Configuration Driver to retrieve
//
HiiValue->Value.string = NewString ((CHAR16 *) Statement->BufferValue, Selection->FormSet->HiiHandle);
} else if (HiiValue->Type == EFI_IFR_TYPE_BUFFER) {
//
// For OrderedList, passing in the value buffer to Callback()
//
TypeValue = (EFI_IFR_TYPE_VALUE *) Statement->BufferValue;
}
Status = ConfigAccess->Callback (
ConfigAccess,
EFI_BROWSER_ACTION_CHANGING,
Statement->QuestionId,
HiiValue->Type,
TypeValue,
&ActionRequest
);
if (HiiValue->Type == EFI_IFR_TYPE_STRING) {
//
// Clean the String in HII Database
//
DeleteString (HiiValue->Value.string, Selection->FormSet->HiiHandle);
}
if (!EFI_ERROR (Status)) {
switch (ActionRequest) {
case EFI_BROWSER_ACTION_REQUEST_RESET:
gResetRequired = TRUE;
break;
case EFI_BROWSER_ACTION_REQUEST_SUBMIT:
SubmitForm (Selection->FormSet, Selection->Form);
break;
case EFI_BROWSER_ACTION_REQUEST_EXIT:
Selection->Action = UI_ACTION_EXIT;
gNvUpdateRequired = FALSE;
break;
default:
break;
}
} else if (Status != EFI_UNSUPPORTED) {
//
// Callback return error status other than EFI_UNSUPPORTED
//
if (Statement->Operand == EFI_IFR_REF_OP) {
//
// Cross reference will not be taken
//
Selection->FormId = Selection->Form->FormId;
Selection->QuestionId = 0;
}
}
}
//
// Check whether Form Package has been updated during Callback
//
if (mHiiPackageListUpdated && (Selection->Action == UI_ACTION_REFRESH_FORM)) {
//
// Force to reparse IFR binary of target Formset
//
mHiiPackageListUpdated = FALSE;
Selection->Action = UI_ACTION_REFRESH_FORMSET;
}
}
} while (Selection->Action == UI_ACTION_REFRESH_FORM);
//
// Before exit the formset, invoke ConfigAccess.Callback() with EFI_BROWSER_ACTION_FORM_CLOSE
//
if ((ConfigAccess != NULL) && (Selection->Action == UI_ACTION_EXIT)) {
ActionRequest = EFI_BROWSER_ACTION_REQUEST_NONE;
Status = ConfigAccess->Callback (
ConfigAccess,
EFI_BROWSER_ACTION_FORM_CLOSE,
0,
EFI_IFR_TYPE_UNDEFINED,
NULL,
&ActionRequest
);
if (!EFI_ERROR (Status)) {
switch (ActionRequest) {
case EFI_BROWSER_ACTION_REQUEST_RESET:
gResetRequired = TRUE;
break;
case EFI_BROWSER_ACTION_REQUEST_SUBMIT:
SubmitForm (Selection->FormSet, Selection->Form);
break;
case EFI_BROWSER_ACTION_REQUEST_EXIT:
gNvUpdateRequired = FALSE;
break;
default:
break;
}
}
}
//
// Record the old formset
//
if (gOldFormSet != NULL) {
DestroyFormSet (gOldFormSet);
}
gOldFormSet = FormSet;
Done:
//
// Unregister notify for Form package update
//
Status = mHiiDatabase->UnregisterPackageNotify (
mHiiDatabase,
NotifyHandle
);
return Status;
}