-/** @file
-Copyright (c) 2004 - 2007, 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.
-
-Module Name:
- Presentation.c
-
-Abstract:
-
- Some presentation routines.
-
-
-**/
-
-#include "Setup.h"
-#include "Ui.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.
-
- @return None.
-
-**/
-VOID
-ClearLines (
- UINTN LeftColumn,
- UINTN RightColumn,
- UINTN TopRow,
- UINTN BottomRow,
- 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);
-
- gBS->FreePool (Buffer);
- return ;
-}
-
-VOID
-NewStrCat (
- CHAR16 *Destination,
- 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);
-}
-
-UINTN
-GetStringWidth (
- 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);
-}
-
-VOID
-DisplayPageFrame (
- VOID
- )
-{
- UINTN Index;
- UINT8 Line;
- UINT8 Alignment;
- CHAR16 Character;
- CHAR16 *Buffer;
- CHAR16 *StrFrontPageBanner;
- UINTN Row;
- EFI_SCREEN_DESCRIPTOR LocalScreen;
-
- 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 == EFI_FRONT_PAGE_SUBCLASS) {
- //
- // 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++
- ) {
- if (BannerData->Banner[Line - (UINT8) LocalScreen.TopRow][Alignment - (UINT8) LocalScreen.LeftColumn] != 0x0000) {
- StrFrontPageBanner = GetToken (
- BannerData->Banner[Line - (UINT8) LocalScreen.TopRow][Alignment - (UINT8) LocalScreen.LeftColumn],
- FrontPageHandle
- );
- } 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;
- }
-
- gBS->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 != EFI_FRONT_PAGE_SUBCLASS) {
- 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 == EFI_SETUP_APPLICATION_SUBCLASS) {
- //
- // 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);
- }
- }
-
- gBS->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) {
- //
- // Postpone Form validation to Question editing or Form submiting
- //
- continue;
- }
-
- Status = EvaluateExpression (FormSet, Form, Expression);
- if (EFI_ERROR (Status)) {
- return Status;
- }
- }
-
- return EFI_SUCCESS;
-}
-
-/*
-+------------------------------------------------------------------------------+
-?F2=Previous Page Setup Page ?
-+------------------------------------------------------------------------------+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-+------------------------------------------------------------------------------+
-?F1=Scroll Help F9=Reset to Defaults F10=Save and Exit ?
-| ^"=Move Highlight <Spacebar> Toggles Checkbox Esc=Discard Changes |
-+------------------------------------------------------------------------------+
-*/
-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;
-
- Handle = Selection->Handle;
- MenuItemCount = 0;
- ArrayEntry = 0;
- OutputString = NULL;
-
- UiInitMenu ();
-
- CopyMem (&LocalScreen, &gScreenDimensions, sizeof (EFI_SCREEN_DESCRIPTOR));
-
- StringPtr = GetToken (Selection->FormSet->FormSetTitle, Handle);
-
- if (gClassOfVfr != EFI_FRONT_PAGE_SUBCLASS) {
- gST->ConOut->SetAttribute (gST->ConOut, TITLE_TEXT | TITLE_BACKGROUND);
- PrintStringAt (
- (LocalScreen.RightColumn + LocalScreen.LeftColumn - GetStringWidth (StringPtr) / 2) / 2,
- LocalScreen.TopRow + 1,
- StringPtr
- );
- }
-
- if (gClassOfVfr == EFI_SETUP_APPLICATION_SUBCLASS) {
- gST->ConOut->SetAttribute (gST->ConOut, KEYHELP_TEXT | KEYHELP_BACKGROUND);
-
- //
- // Display the infrastructure strings
- //
- if (!IsListEmpty (&gMenuList)) {
- PrintStringAt (LocalScreen.LeftColumn + 2, LocalScreen.TopRow + 1, gFunctionTwoString);
- }
-
- PrintStringAt (LocalScreen.LeftColumn + 2, LocalScreen.BottomRow - 4, gFunctionOneString);
- PrintStringAt (
- LocalScreen.LeftColumn + (LocalScreen.RightColumn - LocalScreen.LeftColumn) / 3,
- LocalScreen.BottomRow - 4,
- gFunctionNineString
- );
- PrintStringAt (
- LocalScreen.LeftColumn + (LocalScreen.RightColumn - LocalScreen.LeftColumn) * 2 / 3,
- LocalScreen.BottomRow - 4,
- gFunctionTenString
- );
- PrintAt (LocalScreen.LeftColumn + 2, LocalScreen.BottomRow - 3, L"%c%c%s", ARROW_UP, ARROW_DOWN, gMoveHighlight);
- PrintStringAt (
- LocalScreen.LeftColumn + (LocalScreen.RightColumn - LocalScreen.LeftColumn) / 3,
- LocalScreen.BottomRow - 3,
- gEscapeString
- );
- }
- //
- // Remove Buffer allocated for StringPtr after it has been used.
- //
- gBS->FreePool (StringPtr);
-
- //
- // Evaluate all the Expressions in this Form
- //
- Status = EvaluateFormExpressions (Selection->FormSet, Selection->Form);
- if (EFI_ERROR (Status)) {
- return Status;
- }
-
- 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 (!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])) {
- NumberOfLines++;
- }
-
- gBS->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.
- //
- UiAddMenuOption (StringPtr, Selection->Handle, Statement, NumberOfLines, MenuItemCount);
- MenuItemCount++;
- }
-
- Link = GetNextNode (&Selection->Form->StatementListHead, Link);
- }
-
- Status = UiDisplayMenu (Selection);
-
- UiFreeMenu ();
-
- return Status;
-}
-
-VOID
-InitializeBrowserStrings (
- VOID
- )
-{
- gFunctionOneString = GetToken (STRING_TOKEN (FUNCTION_ONE_STRING), gHiiHandle);
- gFunctionTwoString = GetToken (STRING_TOKEN (FUNCTION_TWO_STRING), gHiiHandle);
- 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);
- 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);
- return ;
-}
-
-VOID
-FreeBrowserStrings (
- VOID
- )
-{
- SafeFreePool (gFunctionOneString);
- SafeFreePool (gFunctionTwoString);
- SafeFreePool (gFunctionNineString);
- SafeFreePool (gFunctionTenString);
- SafeFreePool (gEnterString);
- SafeFreePool (gEnterCommitString);
- SafeFreePool (gEscapeString);
- SafeFreePool (gMoveHighlight);
- SafeFreePool (gMakeSelection);
- SafeFreePool (gDecNumericInput);
- SafeFreePool (gHexNumericInput);
- SafeFreePool (gToggleCheckBox);
- SafeFreePool (gPromptForData);
- SafeFreePool (gPromptForPassword);
- SafeFreePool (gPromptForNewPassword);
- SafeFreePool (gConfirmPassword);
- SafeFreePool (gPassowordInvalid);
- SafeFreePool (gConfirmError);
- SafeFreePool (gPressEnter);
- SafeFreePool (gEmptyString);
- SafeFreePool (gAreYouSure);
- SafeFreePool (gYesResponse);
- SafeFreePool (gNoResponse);
- SafeFreePool (gMiniString);
- SafeFreePool (gPlusString);
- SafeFreePool (gMinusString);
- SafeFreePool (gAdjustNumber);
- return ;
-}
-
-
-/**
- Update key's help imformation
-
- @param MenuOption The Menu option
- @param Selected Whether or not a tag be selected
-
- @return None
-
-**/
-VOID
-UpdateKeyHelp (
- 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;
-
- if (gClassOfVfr == EFI_GENERAL_APPLICATION_SUBCLASS) {
- return ;
- }
-
- 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 == EFI_SETUP_APPLICATION_SUBCLASS) {
- PrintStringAt (StartColumnOfHelp, TopRowOfHelp, gFunctionOneString);
- 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) ||
- (Statement->Operand == EFI_IFR_NUMERIC_OP && Statement->Step != 0)) {
- 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);
- 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) ? 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, gEscapeString);
- }
- break;
-
- case EFI_IFR_CHECKBOX_OP:
- ClearLines (LeftColumnOfHelp, RightColumnOfHelp, TopRowOfHelp, BottomRowOfHelp, KEYHELP_TEXT | KEYHELP_BACKGROUND);
-
- if (gClassOfVfr == EFI_SETUP_APPLICATION_SUBCLASS) {
- PrintStringAt (StartColumnOfHelp, TopRowOfHelp, gFunctionOneString);
- 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 == EFI_SETUP_APPLICATION_SUBCLASS) {
- PrintStringAt (StartColumnOfHelp, TopRowOfHelp, gFunctionOneString);
- 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, gEscapeString);
- }
- }
- break;
-
- default:
- break;
- }
-}
-
-EFI_STATUS
-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;
-}
-
-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;
- FORM_BROWSER_STATEMENT *Statement;
- EFI_HII_CONFIG_ACCESS_PROTOCOL *ConfigAccess;
-
- gMenuRefreshHead = NULL;
- gResetRequired = FALSE;
- gNvUpdateRequired = FALSE;
-
- UiInitMenuList ();
-
- //
- // Register notify for Form package update
- //
- Status = mHiiDatabase->RegisterPackageNotify (
- mHiiDatabase,
- EFI_HII_PACKAGE_FORM,
- NULL,
- FormUpdateNotify,
- EFI_HII_DATABASE_NOTIFY_REMOVE_PACK,
- &NotifyHandle
- );
- if (EFI_ERROR (Status)) {
- return Status;
- }
-
- do {
- //
- // Displays the Header and Footer borders
- //
- DisplayPageFrame ();
-
- //
- // 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);
- }
-
- //
- // Load Questions' Value for display
- //
- Status = LoadFormConfig (Selection->FormSet, Selection->Form);
- if (EFI_ERROR (Status)) {
- return Status;
- }
-
- //
- // 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) {
- gResetRequired = TRUE;
- }
-
- //
- // Reset FormPackage update flag
- //
- mHiiPackageListUpdated = FALSE;
-
- if (Statement->QuestionFlags & EFI_IFR_FLAG_CALLBACK && Statement->Operand != EFI_IFR_PASSWORD_OP) {
- ActionRequest = EFI_BROWSER_ACTION_REQUEST_NONE;
-
- HiiValue = &Statement->HiiValue;
- 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);
- }
-
- ConfigAccess = Selection->FormSet->ConfigAccess;
- if (ConfigAccess == NULL) {
- return EFI_UNSUPPORTED;
- }
- Status = ConfigAccess->Callback (
- ConfigAccess,
- EFI_BROWSER_ACTION_CHANGING,
- Statement->QuestionId,
- HiiValue->Type,
- &HiiValue->Value,
- &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;
- }
- }
- }
-
- //
- // 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
- //
- Selection->Action = UI_ACTION_REFRESH_FORMSET;
- }
- }
- } while (Selection->Action == UI_ACTION_REFRESH_FORM);
-
- //
- // Unregister notify for Form package update
- //
- Status = mHiiDatabase->UnregisterPackageNotify (
- mHiiDatabase,
- NotifyHandle
- );
- return Status;
-}
+/** @file\r
+Utility functions for UI presentation.\r
+\r
+Copyright (c) 2004 - 2013, Intel Corporation. All rights reserved.<BR>\r
+This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD License\r
+which accompanies this distribution. The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#include "Setup.h"\r
+\r
+BOOLEAN mHiiPackageListUpdated;\r
+UI_MENU_SELECTION *gCurrentSelection;\r
+EFI_HII_HANDLE mCurrentHiiHandle = NULL;\r
+EFI_GUID mCurrentFormSetGuid = {0, 0, 0, {0, 0, 0, 0, 0, 0, 0, 0}};\r
+UINT16 mCurrentFormId = 0;\r
+\r
+/**\r
+ Clear retangle with specified text attribute.\r
+\r
+ @param LeftColumn Left column of retangle.\r
+ @param RightColumn Right column of retangle.\r
+ @param TopRow Start row of retangle.\r
+ @param BottomRow End row of retangle.\r
+ @param TextAttribute The character foreground and background.\r
+\r
+**/\r
+VOID\r
+ClearLines (\r
+ IN UINTN LeftColumn,\r
+ IN UINTN RightColumn,\r
+ IN UINTN TopRow,\r
+ IN UINTN BottomRow,\r
+ IN UINTN TextAttribute\r
+ )\r
+{\r
+ CHAR16 *Buffer;\r
+ UINTN Row;\r
+\r
+ //\r
+ // For now, allocate an arbitrarily long buffer\r
+ //\r
+ Buffer = AllocateZeroPool (0x10000);\r
+ ASSERT (Buffer != NULL);\r
+\r
+ //\r
+ // Set foreground and background as defined\r
+ //\r
+ gST->ConOut->SetAttribute (gST->ConOut, TextAttribute);\r
+\r
+ //\r
+ // Much faster to buffer the long string instead of print it a character at a time\r
+ //\r
+ SetUnicodeMem (Buffer, RightColumn - LeftColumn, L' ');\r
+\r
+ //\r
+ // Clear the desired area with the appropriate foreground/background\r
+ //\r
+ for (Row = TopRow; Row <= BottomRow; Row++) {\r
+ PrintStringAt (LeftColumn, Row, Buffer);\r
+ }\r
+\r
+ gST->ConOut->SetCursorPosition (gST->ConOut, LeftColumn, TopRow);\r
+\r
+ FreePool (Buffer);\r
+ return ;\r
+}\r
+\r
+/**\r
+ Concatenate a narrow string to another string.\r
+\r
+ @param Destination The destination string.\r
+ @param Source The source string. The string to be concatenated.\r
+ to the end of Destination.\r
+\r
+**/\r
+VOID\r
+NewStrCat (\r
+ IN OUT CHAR16 *Destination,\r
+ IN CHAR16 *Source\r
+ )\r
+{\r
+ UINTN Length;\r
+\r
+ for (Length = 0; Destination[Length] != 0; Length++)\r
+ ;\r
+\r
+ //\r
+ // We now have the length of the original string\r
+ // We can safely assume for now that we are concatenating a narrow value to this string.\r
+ // For instance, the string is "XYZ" and cat'ing ">"\r
+ // If this assumption changes, we need to make this routine a bit more complex\r
+ //\r
+ Destination[Length] = NARROW_CHAR;\r
+ Length++;\r
+\r
+ StrCpy (Destination + Length, Source);\r
+}\r
+\r
+/**\r
+ Count the storage space of a Unicode string.\r
+\r
+ This function handles the Unicode string with NARROW_CHAR\r
+ and WIDE_CHAR control characters. NARROW_HCAR and WIDE_CHAR\r
+ does not count in the resultant output. If a WIDE_CHAR is\r
+ hit, then 2 Unicode character will consume an output storage\r
+ space with size of CHAR16 till a NARROW_CHAR is hit.\r
+\r
+ If String is NULL, then ASSERT ().\r
+\r
+ @param String The input string to be counted.\r
+\r
+ @return Storage space for the input string.\r
+\r
+**/\r
+UINTN\r
+GetStringWidth (\r
+ IN CHAR16 *String\r
+ )\r
+{\r
+ UINTN Index;\r
+ UINTN Count;\r
+ UINTN IncrementValue;\r
+\r
+ ASSERT (String != NULL);\r
+ if (String == NULL) {\r
+ return 0;\r
+ }\r
+\r
+ Index = 0;\r
+ Count = 0;\r
+ IncrementValue = 1;\r
+\r
+ do {\r
+ //\r
+ // Advance to the null-terminator or to the first width directive\r
+ //\r
+ for (;\r
+ (String[Index] != NARROW_CHAR) && (String[Index] != WIDE_CHAR) && (String[Index] != 0);\r
+ Index++, Count = Count + IncrementValue\r
+ )\r
+ ;\r
+\r
+ //\r
+ // We hit the null-terminator, we now have a count\r
+ //\r
+ if (String[Index] == 0) {\r
+ break;\r
+ }\r
+ //\r
+ // We encountered a narrow directive - strip it from the size calculation since it doesn't get printed\r
+ // and also set the flag that determines what we increment by.(if narrow, increment by 1, if wide increment by 2)\r
+ //\r
+ if (String[Index] == NARROW_CHAR) {\r
+ //\r
+ // Skip to the next character\r
+ //\r
+ Index++;\r
+ IncrementValue = 1;\r
+ } else {\r
+ //\r
+ // Skip to the next character\r
+ //\r
+ Index++;\r
+ IncrementValue = 2;\r
+ }\r
+ } while (String[Index] != 0);\r
+\r
+ //\r
+ // Increment by one to include the null-terminator in the size\r
+ //\r
+ Count++;\r
+\r
+ return Count * sizeof (CHAR16);\r
+}\r
+\r
+/**\r
+ This function displays the page frame.\r
+\r
+ @param Selection Selection contains the information about \r
+ the Selection, form and formset to be displayed.\r
+ Selection action may be updated in retrieve callback.\r
+**/\r
+VOID\r
+DisplayPageFrame (\r
+ IN UI_MENU_SELECTION *Selection\r
+ )\r
+{\r
+ UINTN Index;\r
+ UINT8 Line;\r
+ UINT8 Alignment;\r
+ CHAR16 Character;\r
+ CHAR16 *Buffer;\r
+ CHAR16 *StrFrontPageBanner;\r
+ UINTN Row;\r
+ EFI_SCREEN_DESCRIPTOR LocalScreen;\r
+ UINT8 RowIdx;\r
+ UINT8 ColumnIdx;\r
+\r
+ ZeroMem (&LocalScreen, sizeof (EFI_SCREEN_DESCRIPTOR));\r
+ gST->ConOut->QueryMode (gST->ConOut, gST->ConOut->Mode->Mode, &LocalScreen.RightColumn, &LocalScreen.BottomRow);\r
+ ClearLines (0, LocalScreen.RightColumn, 0, LocalScreen.BottomRow, KEYHELP_BACKGROUND);\r
+\r
+ if (Selection->Form->ModalForm) {\r
+ return;\r
+ }\r
+\r
+ CopyMem (&LocalScreen, &gScreenDimensions, sizeof (EFI_SCREEN_DESCRIPTOR));\r
+\r
+ //\r
+ // For now, allocate an arbitrarily long buffer\r
+ //\r
+ Buffer = AllocateZeroPool (0x10000);\r
+ ASSERT (Buffer != NULL);\r
+\r
+ Character = BOXDRAW_HORIZONTAL;\r
+\r
+ for (Index = 0; Index + 2 < (LocalScreen.RightColumn - LocalScreen.LeftColumn); Index++) {\r
+ Buffer[Index] = Character;\r
+ }\r
+\r
+ if ((gClassOfVfr & FORMSET_CLASS_FRONT_PAGE) == FORMSET_CLASS_FRONT_PAGE) {\r
+ //\r
+ // ClearLines(0, LocalScreen.RightColumn, 0, BANNER_HEIGHT-1, BANNER_TEXT | BANNER_BACKGROUND);\r
+ //\r
+ ClearLines (\r
+ LocalScreen.LeftColumn,\r
+ LocalScreen.RightColumn,\r
+ LocalScreen.TopRow,\r
+ FRONT_PAGE_HEADER_HEIGHT - 1 + LocalScreen.TopRow,\r
+ BANNER_TEXT | BANNER_BACKGROUND\r
+ );\r
+ //\r
+ // for (Line = 0; Line < BANNER_HEIGHT; Line++) {\r
+ //\r
+ for (Line = (UINT8) LocalScreen.TopRow; Line < BANNER_HEIGHT + (UINT8) LocalScreen.TopRow; Line++) {\r
+ //\r
+ // for (Alignment = 0; Alignment < BANNER_COLUMNS; Alignment++) {\r
+ //\r
+ for (Alignment = (UINT8) LocalScreen.LeftColumn;\r
+ Alignment < BANNER_COLUMNS + (UINT8) LocalScreen.LeftColumn;\r
+ Alignment++\r
+ ) {\r
+ RowIdx = (UINT8) (Line - (UINT8) LocalScreen.TopRow);\r
+ ColumnIdx = (UINT8) (Alignment - (UINT8) LocalScreen.LeftColumn);\r
+\r
+ ASSERT (RowIdx < BANNER_HEIGHT);\r
+ ASSERT (ColumnIdx < BANNER_COLUMNS);\r
+\r
+ if (gBannerData->Banner[RowIdx][ColumnIdx] != 0x0000) {\r
+ StrFrontPageBanner = GetToken (\r
+ gBannerData->Banner[RowIdx][ColumnIdx],\r
+ gFrontPageHandle\r
+ );\r
+ } else {\r
+ continue;\r
+ }\r
+\r
+ switch (Alignment - LocalScreen.LeftColumn) {\r
+ case 0:\r
+ //\r
+ // Handle left column\r
+ //\r
+ PrintStringAt (LocalScreen.LeftColumn + BANNER_LEFT_COLUMN_INDENT, Line, StrFrontPageBanner);\r
+ break;\r
+\r
+ case 1:\r
+ //\r
+ // Handle center column\r
+ //\r
+ PrintStringAt (\r
+ LocalScreen.LeftColumn + (LocalScreen.RightColumn - LocalScreen.LeftColumn) / 3,\r
+ Line,\r
+ StrFrontPageBanner\r
+ );\r
+ break;\r
+\r
+ case 2:\r
+ //\r
+ // Handle right column\r
+ //\r
+ PrintStringAt (\r
+ LocalScreen.LeftColumn + (LocalScreen.RightColumn - LocalScreen.LeftColumn) * 2 / 3,\r
+ Line,\r
+ StrFrontPageBanner\r
+ );\r
+ break;\r
+ }\r
+\r
+ FreePool (StrFrontPageBanner);\r
+ }\r
+ }\r
+ }\r
+\r
+ ClearLines (\r
+ LocalScreen.LeftColumn,\r
+ LocalScreen.RightColumn,\r
+ LocalScreen.BottomRow - STATUS_BAR_HEIGHT - gFooterHeight,\r
+ LocalScreen.BottomRow - STATUS_BAR_HEIGHT - 1,\r
+ KEYHELP_TEXT | KEYHELP_BACKGROUND\r
+ );\r
+\r
+ if ((gClassOfVfr & FORMSET_CLASS_FRONT_PAGE) != FORMSET_CLASS_FRONT_PAGE) {\r
+ ClearLines (\r
+ LocalScreen.LeftColumn,\r
+ LocalScreen.RightColumn,\r
+ LocalScreen.TopRow,\r
+ LocalScreen.TopRow + NONE_FRONT_PAGE_HEADER_HEIGHT - 1,\r
+ TITLE_TEXT | TITLE_BACKGROUND\r
+ );\r
+ //\r
+ // Print Top border line\r
+ // +------------------------------------------------------------------------------+\r
+ // ? ?\r
+ // +------------------------------------------------------------------------------+\r
+ //\r
+ Character = BOXDRAW_DOWN_RIGHT;\r
+\r
+ PrintChar (Character);\r
+ PrintString (Buffer);\r
+\r
+ Character = BOXDRAW_DOWN_LEFT;\r
+ PrintChar (Character);\r
+\r
+ Character = BOXDRAW_VERTICAL;\r
+ for (Row = LocalScreen.TopRow + 1; Row <= LocalScreen.TopRow + NONE_FRONT_PAGE_HEADER_HEIGHT - 2; Row++) {\r
+ PrintCharAt (LocalScreen.LeftColumn, Row, Character);\r
+ PrintCharAt (LocalScreen.RightColumn - 1, Row, Character);\r
+ }\r
+\r
+ Character = BOXDRAW_UP_RIGHT;\r
+ PrintCharAt (LocalScreen.LeftColumn, LocalScreen.TopRow + NONE_FRONT_PAGE_HEADER_HEIGHT - 1, Character);\r
+ PrintString (Buffer);\r
+\r
+ Character = BOXDRAW_UP_LEFT;\r
+ PrintChar (Character);\r
+\r
+ if ((gClassOfVfr & FORMSET_CLASS_PLATFORM_SETUP) == FORMSET_CLASS_PLATFORM_SETUP) {\r
+ //\r
+ // Print Bottom border line\r
+ // +------------------------------------------------------------------------------+\r
+ // ? ?\r
+ // +------------------------------------------------------------------------------+\r
+ //\r
+ Character = BOXDRAW_DOWN_RIGHT;\r
+ PrintCharAt (LocalScreen.LeftColumn, LocalScreen.BottomRow - STATUS_BAR_HEIGHT - gFooterHeight, Character);\r
+\r
+ PrintString (Buffer);\r
+\r
+ Character = BOXDRAW_DOWN_LEFT;\r
+ PrintChar (Character);\r
+ Character = BOXDRAW_VERTICAL;\r
+ for (Row = LocalScreen.BottomRow - STATUS_BAR_HEIGHT - gFooterHeight + 1;\r
+ Row <= LocalScreen.BottomRow - STATUS_BAR_HEIGHT - 2;\r
+ Row++\r
+ ) {\r
+ PrintCharAt (LocalScreen.LeftColumn, Row, Character);\r
+ PrintCharAt (LocalScreen.RightColumn - 1, Row, Character);\r
+ }\r
+\r
+ Character = BOXDRAW_UP_RIGHT;\r
+ PrintCharAt (LocalScreen.LeftColumn, LocalScreen.BottomRow - STATUS_BAR_HEIGHT - 1, Character);\r
+\r
+ PrintString (Buffer);\r
+\r
+ Character = BOXDRAW_UP_LEFT;\r
+ PrintChar (Character);\r
+ }\r
+ }\r
+\r
+ FreePool (Buffer);\r
+\r
+}\r
+\r
+\r
+/**\r
+ Evaluate all expressions in a Form.\r
+\r
+ @param FormSet FormSet this Form belongs to.\r
+ @param Form The Form.\r
+\r
+ @retval EFI_SUCCESS The expression evaluated successfuly\r
+\r
+**/\r
+EFI_STATUS\r
+EvaluateFormExpressions (\r
+ IN FORM_BROWSER_FORMSET *FormSet,\r
+ IN FORM_BROWSER_FORM *Form\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ LIST_ENTRY *Link;\r
+ FORM_EXPRESSION *Expression;\r
+\r
+ Link = GetFirstNode (&Form->ExpressionListHead);\r
+ while (!IsNull (&Form->ExpressionListHead, Link)) {\r
+ Expression = FORM_EXPRESSION_FROM_LINK (Link);\r
+ Link = GetNextNode (&Form->ExpressionListHead, Link);\r
+\r
+ if (Expression->Type == EFI_HII_EXPRESSION_INCONSISTENT_IF ||\r
+ Expression->Type == EFI_HII_EXPRESSION_NO_SUBMIT_IF ||\r
+ Expression->Type == EFI_HII_EXPRESSION_WRITE ||\r
+ (Expression->Type == EFI_HII_EXPRESSION_READ && Form->FormType != STANDARD_MAP_FORM_TYPE)) {\r
+ //\r
+ // Postpone Form validation to Question editing or Form submitting or Question Write or Question Read for nonstandard form.\r
+ //\r
+ continue;\r
+ }\r
+\r
+ Status = EvaluateExpression (FormSet, Form, Expression);\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+ }\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+/*\r
++------------------------------------------------------------------------------+\r
+? Setup Page ?\r
++------------------------------------------------------------------------------+\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
++------------------------------------------------------------------------------+\r
+?F1=Scroll Help F9=Reset to Defaults F10=Save and Exit ?\r
+| ^"=Move Highlight <Spacebar> Toggles Checkbox Esc=Discard Changes |\r
++------------------------------------------------------------------------------+\r
+*/\r
+\r
+/**\r
+\r
+\r
+ Display form and wait for user to select one menu option, then return it.\r
+\r
+ @param Selection On input, Selection tell setup browser the information\r
+ about the Selection, form and formset to be displayed.\r
+ On output, Selection return the screen item that is selected\r
+ by user.\r
+ @retval EFI_SUCESSS This function always return successfully for now.\r
+\r
+**/\r
+EFI_STATUS\r
+DisplayForm (\r
+ IN OUT UI_MENU_SELECTION *Selection\r
+ )\r
+{\r
+ CHAR16 *StringPtr;\r
+ UINT16 MenuItemCount;\r
+ EFI_HII_HANDLE Handle;\r
+ EFI_SCREEN_DESCRIPTOR LocalScreen;\r
+ UINT16 Width;\r
+ UINTN ArrayEntry;\r
+ CHAR16 *OutputString;\r
+ LIST_ENTRY *Link;\r
+ FORM_BROWSER_STATEMENT *Statement;\r
+ UINT16 NumberOfLines;\r
+ EFI_STATUS Status;\r
+ UI_MENU_OPTION *MenuOption;\r
+ UINT16 GlyphWidth;\r
+\r
+ Handle = Selection->Handle;\r
+ MenuItemCount = 0;\r
+ ArrayEntry = 0;\r
+ OutputString = NULL;\r
+\r
+ UiInitMenu ();\r
+\r
+ CopyMem (&LocalScreen, &gScreenDimensions, sizeof (EFI_SCREEN_DESCRIPTOR));\r
+\r
+ StringPtr = GetToken (Selection->Form->FormTitle, Handle);\r
+\r
+ if ((gClassOfVfr & FORMSET_CLASS_FRONT_PAGE) != FORMSET_CLASS_FRONT_PAGE) {\r
+ if (Selection->Form->ModalForm) {\r
+ gST->ConOut->SetAttribute (gST->ConOut, TITLE_TEXT | EFI_BACKGROUND_BLACK);\r
+ } else {\r
+ gST->ConOut->SetAttribute (gST->ConOut, TITLE_TEXT | TITLE_BACKGROUND);\r
+ }\r
+ PrintStringAt (\r
+ (LocalScreen.RightColumn + LocalScreen.LeftColumn - GetStringWidth (StringPtr) / 2) / 2,\r
+ LocalScreen.TopRow + 1,\r
+ StringPtr\r
+ );\r
+ }\r
+\r
+ //\r
+ // Remove Buffer allocated for StringPtr after it has been used.\r
+ //\r
+ FreePool (StringPtr);\r
+\r
+ //\r
+ // Evaluate all the Expressions in this Form\r
+ //\r
+ Status = EvaluateFormExpressions (Selection->FormSet, Selection->Form);\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ Selection->FormEditable = FALSE;\r
+ Link = GetFirstNode (&Selection->Form->StatementListHead);\r
+ while (!IsNull (&Selection->Form->StatementListHead, Link)) {\r
+ Statement = FORM_BROWSER_STATEMENT_FROM_LINK (Link);\r
+\r
+ if (EvaluateExpressionList(Statement->Expression, FALSE, NULL, NULL) <= ExpressGrayOut) {\r
+ StringPtr = GetToken (Statement->Prompt, Handle);\r
+ ASSERT (StringPtr != NULL);\r
+\r
+ Width = GetWidth (Statement, Handle);\r
+\r
+ NumberOfLines = 1;\r
+ ArrayEntry = 0;\r
+ GlyphWidth = 1;\r
+ for (; GetLineByWidth (StringPtr, Width, &GlyphWidth,&ArrayEntry, &OutputString) != 0x0000;) {\r
+ //\r
+ // If there is more string to process print on the next row and increment the Skip value\r
+ //\r
+ if (StrLen (&StringPtr[ArrayEntry]) != 0) {\r
+ NumberOfLines++;\r
+ }\r
+\r
+ FreePool (OutputString);\r
+ }\r
+\r
+ //\r
+ // We are NOT!! removing this StringPtr buffer via FreePool since it is being used in the menuoptions, we will do\r
+ // it in UiFreeMenu.\r
+ //\r
+ MenuOption = UiAddMenuOption (StringPtr, Selection->Handle, Selection->Form, Statement, NumberOfLines, MenuItemCount);\r
+ MenuItemCount++;\r
+\r
+ if (MenuOption->IsQuestion && !MenuOption->ReadOnly) {\r
+ //\r
+ // At least one item is not readonly, this Form is considered as editable\r
+ //\r
+ Selection->FormEditable = TRUE;\r
+ }\r
+ }\r
+\r
+ Link = GetNextNode (&Selection->Form->StatementListHead, Link);\r
+ }\r
+\r
+ Status = UiDisplayMenu (Selection);\r
+\r
+ UiFreeMenu ();\r
+\r
+ return Status;\r
+}\r
+\r
+/**\r
+ Initialize the HII String Token to the correct values.\r
+\r
+**/\r
+VOID\r
+InitializeBrowserStrings (\r
+ VOID\r
+ )\r
+{\r
+ gEnterString = GetToken (STRING_TOKEN (ENTER_STRING), gHiiHandle);\r
+ gEnterCommitString = GetToken (STRING_TOKEN (ENTER_COMMIT_STRING), gHiiHandle);\r
+ gEnterEscapeString = GetToken (STRING_TOKEN (ENTER_ESCAPE_STRING), gHiiHandle);\r
+ gEscapeString = GetToken (STRING_TOKEN (ESCAPE_STRING), gHiiHandle);\r
+ gMoveHighlight = GetToken (STRING_TOKEN (MOVE_HIGHLIGHT), gHiiHandle);\r
+ gMakeSelection = GetToken (STRING_TOKEN (MAKE_SELECTION), gHiiHandle);\r
+ gDecNumericInput = GetToken (STRING_TOKEN (DEC_NUMERIC_INPUT), gHiiHandle);\r
+ gHexNumericInput = GetToken (STRING_TOKEN (HEX_NUMERIC_INPUT), gHiiHandle);\r
+ gToggleCheckBox = GetToken (STRING_TOKEN (TOGGLE_CHECK_BOX), gHiiHandle);\r
+ gPromptForData = GetToken (STRING_TOKEN (PROMPT_FOR_DATA), gHiiHandle);\r
+ gPromptForPassword = GetToken (STRING_TOKEN (PROMPT_FOR_PASSWORD), gHiiHandle);\r
+ gPromptForNewPassword = GetToken (STRING_TOKEN (PROMPT_FOR_NEW_PASSWORD), gHiiHandle);\r
+ gConfirmPassword = GetToken (STRING_TOKEN (CONFIRM_PASSWORD), gHiiHandle);\r
+ gConfirmError = GetToken (STRING_TOKEN (CONFIRM_ERROR), gHiiHandle);\r
+ gPassowordInvalid = GetToken (STRING_TOKEN (PASSWORD_INVALID), gHiiHandle);\r
+ gPressEnter = GetToken (STRING_TOKEN (PRESS_ENTER), gHiiHandle);\r
+ gEmptyString = GetToken (STRING_TOKEN (EMPTY_STRING), gHiiHandle);\r
+ gAreYouSure = GetToken (STRING_TOKEN (ARE_YOU_SURE), gHiiHandle);\r
+ gYesResponse = GetToken (STRING_TOKEN (ARE_YOU_SURE_YES), gHiiHandle);\r
+ gNoResponse = GetToken (STRING_TOKEN (ARE_YOU_SURE_NO), gHiiHandle);\r
+ gMiniString = GetToken (STRING_TOKEN (MINI_STRING), gHiiHandle);\r
+ gPlusString = GetToken (STRING_TOKEN (PLUS_STRING), gHiiHandle);\r
+ gMinusString = GetToken (STRING_TOKEN (MINUS_STRING), gHiiHandle);\r
+ gAdjustNumber = GetToken (STRING_TOKEN (ADJUST_NUMBER), gHiiHandle);\r
+ gSaveChanges = GetToken (STRING_TOKEN (SAVE_CHANGES), gHiiHandle);\r
+ gOptionMismatch = GetToken (STRING_TOKEN (OPTION_MISMATCH), gHiiHandle);\r
+ gFormSuppress = GetToken (STRING_TOKEN (FORM_SUPPRESSED), gHiiHandle);\r
+ gProtocolNotFound = GetToken (STRING_TOKEN (PROTOCOL_NOT_FOUND), gHiiHandle);\r
+ return ;\r
+}\r
+\r
+/**\r
+ Free up the resource allocated for all strings required\r
+ by Setup Browser.\r
+\r
+**/\r
+VOID\r
+FreeBrowserStrings (\r
+ VOID\r
+ )\r
+{\r
+ FreePool (gEnterString);\r
+ FreePool (gEnterCommitString);\r
+ FreePool (gEnterEscapeString);\r
+ FreePool (gEscapeString);\r
+ FreePool (gMoveHighlight);\r
+ FreePool (gMakeSelection);\r
+ FreePool (gDecNumericInput);\r
+ FreePool (gHexNumericInput);\r
+ FreePool (gToggleCheckBox);\r
+ FreePool (gPromptForData);\r
+ FreePool (gPromptForPassword);\r
+ FreePool (gPromptForNewPassword);\r
+ FreePool (gConfirmPassword);\r
+ FreePool (gPassowordInvalid);\r
+ FreePool (gConfirmError);\r
+ FreePool (gPressEnter);\r
+ FreePool (gEmptyString);\r
+ FreePool (gAreYouSure);\r
+ FreePool (gYesResponse);\r
+ FreePool (gNoResponse);\r
+ FreePool (gMiniString);\r
+ FreePool (gPlusString);\r
+ FreePool (gMinusString);\r
+ FreePool (gAdjustNumber);\r
+ FreePool (gSaveChanges);\r
+ FreePool (gOptionMismatch);\r
+ FreePool (gFormSuppress);\r
+ FreePool (gProtocolNotFound);\r
+ return ;\r
+}\r
+\r
+/**\r
+ Show all registered HotKey help strings on bottom Rows.\r
+\r
+**/\r
+VOID\r
+PrintHotKeyHelpString (\r
+ VOID\r
+ )\r
+{\r
+ UINTN CurrentCol;\r
+ UINTN CurrentRow;\r
+ UINTN BottomRowOfHotKeyHelp;\r
+ UINTN ColumnWidth;\r
+ UINTN Index;\r
+ EFI_SCREEN_DESCRIPTOR LocalScreen;\r
+ LIST_ENTRY *Link;\r
+ BROWSER_HOT_KEY *HotKey;\r
+\r
+ CopyMem (&LocalScreen, &gScreenDimensions, sizeof (EFI_SCREEN_DESCRIPTOR));\r
+ ColumnWidth = (LocalScreen.RightColumn - LocalScreen.LeftColumn) / 3;\r
+ BottomRowOfHotKeyHelp = LocalScreen.BottomRow - STATUS_BAR_HEIGHT - 3;\r
+\r
+ //\r
+ // Calculate total number of Register HotKeys. \r
+ //\r
+ Index = 0;\r
+ Link = GetFirstNode (&gBrowserHotKeyList);\r
+ while (!IsNull (&gBrowserHotKeyList, Link)) {\r
+ HotKey = BROWSER_HOT_KEY_FROM_LINK (Link);\r
+ //\r
+ // Help string can't exceed ColumnWidth. One Row will show three Help information. \r
+ //\r
+ if (StrLen (HotKey->HelpString) > ColumnWidth) {\r
+ HotKey->HelpString[ColumnWidth] = L'\0';\r
+ }\r
+ //\r
+ // Calculate help information Column and Row.\r
+ //\r
+ if ((Index % 3) != 2) {\r
+ CurrentCol = LocalScreen.LeftColumn + (2 - Index % 3) * ColumnWidth;\r
+ } else {\r
+ CurrentCol = LocalScreen.LeftColumn + 2;\r
+ }\r
+ CurrentRow = BottomRowOfHotKeyHelp - Index / 3;\r
+ //\r
+ // Print HotKey help string on bottom Row.\r
+ //\r
+ PrintStringAt (CurrentCol, CurrentRow, HotKey->HelpString);\r
+\r
+ //\r
+ // Get Next Hot Key.\r
+ //\r
+ Link = GetNextNode (&gBrowserHotKeyList, Link);\r
+ Index ++;\r
+ }\r
+ \r
+ return;\r
+}\r
+\r
+/**\r
+ Update key's help imformation.\r
+\r
+ @param Selection Tell setup browser the information about the Selection\r
+ @param MenuOption The Menu option\r
+ @param Selected Whether or not a tag be selected\r
+\r
+**/\r
+VOID\r
+UpdateKeyHelp (\r
+ IN UI_MENU_SELECTION *Selection,\r
+ IN UI_MENU_OPTION *MenuOption,\r
+ IN BOOLEAN Selected\r
+ )\r
+{\r
+ UINTN SecCol;\r
+ UINTN ThdCol;\r
+ UINTN LeftColumnOfHelp;\r
+ UINTN RightColumnOfHelp;\r
+ UINTN TopRowOfHelp;\r
+ UINTN BottomRowOfHelp;\r
+ UINTN StartColumnOfHelp;\r
+ EFI_SCREEN_DESCRIPTOR LocalScreen;\r
+ FORM_BROWSER_STATEMENT *Statement;\r
+\r
+ gST->ConOut->SetAttribute (gST->ConOut, KEYHELP_TEXT | KEYHELP_BACKGROUND);\r
+\r
+ if (Selection->Form->ModalForm) {\r
+ return;\r
+ }\r
+\r
+ CopyMem (&LocalScreen, &gScreenDimensions, sizeof (EFI_SCREEN_DESCRIPTOR));\r
+\r
+ SecCol = LocalScreen.LeftColumn + (LocalScreen.RightColumn - LocalScreen.LeftColumn) / 3;\r
+ ThdCol = LocalScreen.LeftColumn + (LocalScreen.RightColumn - LocalScreen.LeftColumn) / 3 * 2;\r
+\r
+ StartColumnOfHelp = LocalScreen.LeftColumn + 2;\r
+ LeftColumnOfHelp = LocalScreen.LeftColumn + 1;\r
+ RightColumnOfHelp = LocalScreen.RightColumn - 2;\r
+ TopRowOfHelp = LocalScreen.BottomRow - STATUS_BAR_HEIGHT - gFooterHeight + 1;\r
+ BottomRowOfHelp = LocalScreen.BottomRow - STATUS_BAR_HEIGHT - 2;\r
+\r
+ Statement = MenuOption->ThisTag;\r
+ switch (Statement->Operand) {\r
+ case EFI_IFR_ORDERED_LIST_OP:\r
+ case EFI_IFR_ONE_OF_OP:\r
+ case EFI_IFR_NUMERIC_OP:\r
+ case EFI_IFR_TIME_OP:\r
+ case EFI_IFR_DATE_OP:\r
+ ClearLines (LeftColumnOfHelp, RightColumnOfHelp, TopRowOfHelp, BottomRowOfHelp, KEYHELP_TEXT | KEYHELP_BACKGROUND);\r
+\r
+ if (!Selected) {\r
+ //\r
+ // On system setting, HotKey will show on every form.\r
+ //\r
+ if (gBrowserSettingScope == SystemLevel ||\r
+ (Selection->FormEditable && gFunctionKeySetting != NONE_FUNCTION_KEY_SETTING)) {\r
+ PrintHotKeyHelpString ();\r
+ }\r
+\r
+ if ((gClassOfVfr & FORMSET_CLASS_PLATFORM_SETUP) == FORMSET_CLASS_PLATFORM_SETUP) {\r
+ PrintStringAt (ThdCol, BottomRowOfHelp, gEscapeString);\r
+ }\r
+\r
+ if ((Statement->Operand == EFI_IFR_DATE_OP) ||\r
+ (Statement->Operand == EFI_IFR_TIME_OP)) {\r
+ PrintAt (\r
+ StartColumnOfHelp,\r
+ BottomRowOfHelp,\r
+ L"%c%c%c%c%s",\r
+ ARROW_UP,\r
+ ARROW_DOWN,\r
+ ARROW_RIGHT,\r
+ ARROW_LEFT,\r
+ gMoveHighlight\r
+ );\r
+ PrintStringAt (SecCol, BottomRowOfHelp, gEnterString);\r
+ PrintStringAt (StartColumnOfHelp, TopRowOfHelp, gAdjustNumber);\r
+ } else {\r
+ PrintAt (StartColumnOfHelp, BottomRowOfHelp, L"%c%c%s", ARROW_UP, ARROW_DOWN, gMoveHighlight);\r
+ if (Statement->Operand == EFI_IFR_NUMERIC_OP && Statement->Step != 0) {\r
+ PrintStringAt (StartColumnOfHelp, TopRowOfHelp, gAdjustNumber);\r
+ } \r
+ PrintStringAt (SecCol, BottomRowOfHelp, gEnterString);\r
+ }\r
+ } else {\r
+ PrintStringAt (SecCol, BottomRowOfHelp, gEnterCommitString);\r
+\r
+ //\r
+ // If it is a selected numeric with manual input, display different message\r
+ //\r
+ if ((Statement->Operand == EFI_IFR_NUMERIC_OP) || \r
+ (Statement->Operand == EFI_IFR_DATE_OP) ||\r
+ (Statement->Operand == EFI_IFR_TIME_OP)) {\r
+ PrintStringAt (\r
+ SecCol,\r
+ TopRowOfHelp,\r
+ ((Statement->Flags & EFI_IFR_DISPLAY_UINT_HEX) == EFI_IFR_DISPLAY_UINT_HEX) ? gHexNumericInput : gDecNumericInput\r
+ );\r
+ } else if (Statement->Operand != EFI_IFR_ORDERED_LIST_OP) {\r
+ PrintAt (StartColumnOfHelp, BottomRowOfHelp, L"%c%c%s", ARROW_UP, ARROW_DOWN, gMoveHighlight);\r
+ }\r
+\r
+ if (Statement->Operand == EFI_IFR_ORDERED_LIST_OP) {\r
+ PrintStringAt (StartColumnOfHelp, TopRowOfHelp, gPlusString);\r
+ PrintStringAt (ThdCol, TopRowOfHelp, gMinusString);\r
+ }\r
+\r
+ PrintStringAt (ThdCol, BottomRowOfHelp, gEnterEscapeString);\r
+ }\r
+ break;\r
+\r
+ case EFI_IFR_CHECKBOX_OP:\r
+ ClearLines (LeftColumnOfHelp, RightColumnOfHelp, TopRowOfHelp, BottomRowOfHelp, KEYHELP_TEXT | KEYHELP_BACKGROUND);\r
+\r
+ //\r
+ // On system setting, HotKey will show on every form.\r
+ //\r
+ if (gBrowserSettingScope == SystemLevel ||\r
+ (Selection->FormEditable && gFunctionKeySetting != NONE_FUNCTION_KEY_SETTING)) {\r
+ PrintHotKeyHelpString ();\r
+ }\r
+ if ((gClassOfVfr & FORMSET_CLASS_PLATFORM_SETUP) == FORMSET_CLASS_PLATFORM_SETUP) {\r
+ PrintStringAt (ThdCol, BottomRowOfHelp, gEscapeString);\r
+ }\r
+\r
+ PrintAt (StartColumnOfHelp, BottomRowOfHelp, L"%c%c%s", ARROW_UP, ARROW_DOWN, gMoveHighlight);\r
+ PrintStringAt (SecCol, BottomRowOfHelp, gToggleCheckBox);\r
+ break;\r
+\r
+ case EFI_IFR_REF_OP:\r
+ case EFI_IFR_PASSWORD_OP:\r
+ case EFI_IFR_STRING_OP:\r
+ case EFI_IFR_TEXT_OP:\r
+ case EFI_IFR_ACTION_OP:\r
+ case EFI_IFR_RESET_BUTTON_OP:\r
+ case EFI_IFR_SUBTITLE_OP:\r
+ ClearLines (LeftColumnOfHelp, RightColumnOfHelp, TopRowOfHelp, BottomRowOfHelp, KEYHELP_TEXT | KEYHELP_BACKGROUND);\r
+\r
+ if (!Selected) {\r
+ //\r
+ // On system setting, HotKey will show on every form.\r
+ //\r
+ if (gBrowserSettingScope == SystemLevel ||\r
+ (Selection->FormEditable && gFunctionKeySetting != NONE_FUNCTION_KEY_SETTING)) {\r
+ PrintHotKeyHelpString ();\r
+ }\r
+ if ((gClassOfVfr & FORMSET_CLASS_PLATFORM_SETUP) == FORMSET_CLASS_PLATFORM_SETUP) {\r
+ PrintStringAt (ThdCol, BottomRowOfHelp, gEscapeString);\r
+ }\r
+\r
+ PrintAt (StartColumnOfHelp, BottomRowOfHelp, L"%c%c%s", ARROW_UP, ARROW_DOWN, gMoveHighlight);\r
+ if (Statement->Operand != EFI_IFR_TEXT_OP && Statement->Operand != EFI_IFR_SUBTITLE_OP) {\r
+ PrintStringAt (SecCol, BottomRowOfHelp, gEnterString);\r
+ }\r
+ } else {\r
+ if (Statement->Operand != EFI_IFR_REF_OP) {\r
+ PrintStringAt (\r
+ (LocalScreen.RightColumn - GetStringWidth (gEnterCommitString) / 2) / 2,\r
+ BottomRowOfHelp,\r
+ gEnterCommitString\r
+ );\r
+ PrintStringAt (ThdCol, BottomRowOfHelp, gEnterEscapeString);\r
+ }\r
+ }\r
+ break;\r
+\r
+ default:\r
+ break;\r
+ }\r
+}\r
+\r
+/**\r
+ Functions which are registered to receive notification of\r
+ database events have this prototype. The actual event is encoded\r
+ in NotifyType. The following table describes how PackageType,\r
+ PackageGuid, Handle, and Package are used for each of the\r
+ notification types.\r
+\r
+ @param PackageType Package type of the notification.\r
+\r
+ @param PackageGuid If PackageType is\r
+ EFI_HII_PACKAGE_TYPE_GUID, then this is\r
+ the pointer to the GUID from the Guid\r
+ field of EFI_HII_PACKAGE_GUID_HEADER.\r
+ Otherwise, it must be NULL.\r
+\r
+ @param Package Points to the package referred to by the\r
+ notification Handle The handle of the package\r
+ list which contains the specified package.\r
+\r
+ @param Handle The HII handle.\r
+\r
+ @param NotifyType The type of change concerning the\r
+ database. See\r
+ EFI_HII_DATABASE_NOTIFY_TYPE.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+FormUpdateNotify (\r
+ IN UINT8 PackageType,\r
+ IN CONST EFI_GUID *PackageGuid,\r
+ IN CONST EFI_HII_PACKAGE_HEADER *Package,\r
+ IN EFI_HII_HANDLE Handle,\r
+ IN EFI_HII_DATABASE_NOTIFY_TYPE NotifyType\r
+ )\r
+{\r
+ mHiiPackageListUpdated = TRUE;\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+ check whether the formset need to update the NV.\r
+\r
+ @param FormSet FormSet data structure.\r
+\r
+ @retval TRUE Need to update the NV.\r
+ @retval FALSE No need to update the NV.\r
+**/\r
+BOOLEAN \r
+IsNvUpdateRequired (\r
+ IN FORM_BROWSER_FORMSET *FormSet\r
+ )\r
+{\r
+ LIST_ENTRY *Link;\r
+ FORM_BROWSER_FORM *Form;\r
+\r
+ Link = GetFirstNode (&FormSet->FormListHead);\r
+ while (!IsNull (&FormSet->FormListHead, Link)) {\r
+ Form = FORM_BROWSER_FORM_FROM_LINK (Link);\r
+\r
+ if (Form->NvUpdateRequired ) {\r
+ return TRUE;\r
+ }\r
+\r
+ Link = GetNextNode (&FormSet->FormListHead, Link);\r
+ }\r
+\r
+ return FALSE;\r
+}\r
+\r
+/**\r
+ check whether the formset need to update the NV.\r
+\r
+ @param FormSet FormSet data structure.\r
+ @param SetValue Whether set new value or clear old value.\r
+\r
+**/\r
+VOID\r
+UpdateNvInfoInForm (\r
+ IN FORM_BROWSER_FORMSET *FormSet,\r
+ IN BOOLEAN SetValue\r
+ )\r
+{\r
+ LIST_ENTRY *Link;\r
+ FORM_BROWSER_FORM *Form;\r
+ \r
+ Link = GetFirstNode (&FormSet->FormListHead);\r
+ while (!IsNull (&FormSet->FormListHead, Link)) {\r
+ Form = FORM_BROWSER_FORM_FROM_LINK (Link);\r
+\r
+ Form->NvUpdateRequired = SetValue;\r
+\r
+ Link = GetNextNode (&FormSet->FormListHead, Link);\r
+ }\r
+}\r
+/**\r
+ Find menu which will show next time.\r
+\r
+ @param Selection On input, Selection tell setup browser the information\r
+ about the Selection, form and formset to be displayed.\r
+ On output, Selection return the screen item that is selected\r
+ by user.\r
+ @param Repaint Whether need to repaint the menu.\r
+ @param NewLine Whether need to show at new line.\r
+ \r
+ @retval TRUE Need return.\r
+ @retval FALSE No need to return.\r
+**/\r
+BOOLEAN\r
+FindNextMenu (\r
+ IN OUT UI_MENU_SELECTION *Selection,\r
+ IN BOOLEAN *Repaint, \r
+ IN BOOLEAN *NewLine \r
+ )\r
+{\r
+ UI_MENU_LIST *CurrentMenu;\r
+ CHAR16 YesResponse;\r
+ CHAR16 NoResponse;\r
+ EFI_INPUT_KEY Key;\r
+ BROWSER_SETTING_SCOPE Scope;\r
+ \r
+ CurrentMenu = Selection->CurrentMenu;\r
+\r
+ if (CurrentMenu != NULL && CurrentMenu->Parent != NULL) {\r
+ //\r
+ // we have a parent, so go to the parent menu\r
+ //\r
+ if (CompareGuid (&CurrentMenu->FormSetGuid, &CurrentMenu->Parent->FormSetGuid)) {\r
+ //\r
+ // The parent menu and current menu are in the same formset\r
+ //\r
+ Selection->Action = UI_ACTION_REFRESH_FORM;\r
+ Scope = FormLevel;\r
+ } else {\r
+ Selection->Action = UI_ACTION_REFRESH_FORMSET;\r
+ CopyMem (&Selection->FormSetGuid, &CurrentMenu->Parent->FormSetGuid, sizeof (EFI_GUID));\r
+ Selection->Handle = CurrentMenu->Parent->HiiHandle;\r
+ Scope = FormSetLevel;\r
+ }\r
+\r
+ //\r
+ // Form Level Check whether the data is changed.\r
+ //\r
+ if ((gBrowserSettingScope == FormLevel && Selection->Form->NvUpdateRequired) ||\r
+ (gBrowserSettingScope == FormSetLevel && IsNvUpdateRequired(Selection->FormSet) && Scope == FormSetLevel)) {\r
+ gST->ConIn->ReadKeyStroke (gST->ConIn, &Key);\r
+ \r
+ YesResponse = gYesResponse[0];\r
+ NoResponse = gNoResponse[0];\r
+ \r
+ //\r
+ // If NV flag is up, prompt user\r
+ //\r
+ do {\r
+ CreateDialog (4, TRUE, 0, NULL, &Key, gEmptyString, gSaveChanges, gAreYouSure, gEmptyString);\r
+ } while\r
+ (\r
+ (Key.ScanCode != SCAN_ESC) &&\r
+ ((Key.UnicodeChar | UPPER_LOWER_CASE_OFFSET) != (NoResponse | UPPER_LOWER_CASE_OFFSET)) &&\r
+ ((Key.UnicodeChar | UPPER_LOWER_CASE_OFFSET) != (YesResponse | UPPER_LOWER_CASE_OFFSET))\r
+ );\r
+ \r
+ if (Key.ScanCode == SCAN_ESC) {\r
+ //\r
+ // User hits the ESC key, Ingore. \r
+ //\r
+ if (Repaint != NULL) {\r
+ *Repaint = TRUE;\r
+ }\r
+ if (NewLine != NULL) {\r
+ *NewLine = TRUE;\r
+ }\r
+\r
+ Selection->Action = UI_ACTION_NONE;\r
+ return FALSE;\r
+ }\r
+ \r
+ if ((Key.UnicodeChar | UPPER_LOWER_CASE_OFFSET) == (YesResponse | UPPER_LOWER_CASE_OFFSET)) {\r
+ //\r
+ // If the user hits the YesResponse key\r
+ //\r
+ SubmitForm (Selection->FormSet, Selection->Form, Scope);\r
+ } else {\r
+ //\r
+ // If the user hits the NoResponse key\r
+ //\r
+ DiscardForm (Selection->FormSet, Selection->Form, Scope);\r
+ }\r
+ }\r
+\r
+ Selection->Statement = NULL;\r
+\r
+ Selection->FormId = CurrentMenu->Parent->FormId;\r
+ Selection->QuestionId = CurrentMenu->Parent->QuestionId;\r
+\r
+ //\r
+ // Clear highlight record for this menu\r
+ //\r
+ CurrentMenu->QuestionId = 0;\r
+ return FALSE;\r
+ }\r
+\r
+ if ((gClassOfVfr & FORMSET_CLASS_FRONT_PAGE) == FORMSET_CLASS_FRONT_PAGE) {\r
+ //\r
+ // We never exit FrontPage, so skip the ESC\r
+ //\r
+ Selection->Action = UI_ACTION_NONE;\r
+ return FALSE;\r
+ }\r
+\r
+ //\r
+ // We are going to leave current FormSet, so check uncommited data in this FormSet\r
+ //\r
+ if (gBrowserSettingScope != SystemLevel && IsNvUpdateRequired(Selection->FormSet)) {\r
+ gST->ConIn->ReadKeyStroke (gST->ConIn, &Key);\r
+\r
+ YesResponse = gYesResponse[0];\r
+ NoResponse = gNoResponse[0];\r
+\r
+ //\r
+ // If NV flag is up, prompt user\r
+ //\r
+ do {\r
+ CreateDialog (4, TRUE, 0, NULL, &Key, gEmptyString, gSaveChanges, gAreYouSure, gEmptyString);\r
+ } while\r
+ (\r
+ (Key.ScanCode != SCAN_ESC) &&\r
+ ((Key.UnicodeChar | UPPER_LOWER_CASE_OFFSET) != (NoResponse | UPPER_LOWER_CASE_OFFSET)) &&\r
+ ((Key.UnicodeChar | UPPER_LOWER_CASE_OFFSET) != (YesResponse | UPPER_LOWER_CASE_OFFSET))\r
+ );\r
+\r
+ if (Key.ScanCode == SCAN_ESC) {\r
+ //\r
+ // User hits the ESC key\r
+ //\r
+ if (Repaint != NULL) {\r
+ *Repaint = TRUE;\r
+ }\r
+\r
+ if (NewLine != NULL) {\r
+ *NewLine = TRUE;\r
+ }\r
+\r
+ Selection->Action = UI_ACTION_NONE;\r
+ return FALSE;\r
+ }\r
+\r
+ if ((Key.UnicodeChar | UPPER_LOWER_CASE_OFFSET) == (YesResponse | UPPER_LOWER_CASE_OFFSET)) {\r
+ //\r
+ // If the user hits the YesResponse key\r
+ //\r
+ SubmitForm (Selection->FormSet, Selection->Form, FormSetLevel);\r
+ } else {\r
+ //\r
+ // If the user hits the NoResponse key\r
+ //\r
+ DiscardForm (Selection->FormSet, Selection->Form, FormSetLevel);\r
+ }\r
+ }\r
+\r
+ Selection->Statement = NULL;\r
+ if (CurrentMenu != NULL) {\r
+ CurrentMenu->QuestionId = 0;\r
+ }\r
+\r
+ Selection->Action = UI_ACTION_EXIT;\r
+ return TRUE;\r
+}\r
+\r
+/**\r
+ Call the call back function for the question and process the return action.\r
+\r
+ @param Selection On input, Selection tell setup browser the information\r
+ about the Selection, form and formset to be displayed.\r
+ On output, Selection return the screen item that is selected\r
+ by user.\r
+ @param Question The Question which need to call.\r
+ @param Action The action request.\r
+ @param SkipSaveOrDiscard Whether skip save or discard action.\r
+\r
+ @retval EFI_SUCCESS The call back function excutes successfully.\r
+ @return Other value if the call back function failed to excute. \r
+**/\r
+EFI_STATUS \r
+ProcessCallBackFunction (\r
+ IN OUT UI_MENU_SELECTION *Selection,\r
+ IN FORM_BROWSER_STATEMENT *Question,\r
+ IN EFI_BROWSER_ACTION Action,\r
+ IN BOOLEAN SkipSaveOrDiscard\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ EFI_BROWSER_ACTION_REQUEST ActionRequest;\r
+ EFI_HII_CONFIG_ACCESS_PROTOCOL *ConfigAccess;\r
+ EFI_HII_VALUE *HiiValue;\r
+ EFI_IFR_TYPE_VALUE *TypeValue;\r
+ FORM_BROWSER_STATEMENT *Statement;\r
+ BOOLEAN SubmitFormIsRequired;\r
+ BOOLEAN DiscardFormIsRequired;\r
+ BOOLEAN NeedExit;\r
+ LIST_ENTRY *Link;\r
+ BROWSER_SETTING_SCOPE SettingLevel;\r
+\r
+ ConfigAccess = Selection->FormSet->ConfigAccess;\r
+ SubmitFormIsRequired = FALSE;\r
+ SettingLevel = FormSetLevel;\r
+ DiscardFormIsRequired = FALSE;\r
+ NeedExit = FALSE;\r
+ Status = EFI_SUCCESS;\r
+ ActionRequest = EFI_BROWSER_ACTION_REQUEST_NONE;\r
+\r
+ if (ConfigAccess == NULL) {\r
+ return EFI_SUCCESS;\r
+ }\r
+\r
+ Link = GetFirstNode (&Selection->Form->StatementListHead);\r
+ while (!IsNull (&Selection->Form->StatementListHead, Link)) {\r
+ Statement = FORM_BROWSER_STATEMENT_FROM_LINK (Link);\r
+ Link = GetNextNode (&Selection->Form->StatementListHead, Link);\r
+\r
+ //\r
+ // if Question != NULL, only process the question. Else, process all question in this form.\r
+ //\r
+ if ((Question != NULL) && (Statement != Question)) {\r
+ continue;\r
+ }\r
+ \r
+ if ((Statement->QuestionFlags & EFI_IFR_FLAG_CALLBACK) != EFI_IFR_FLAG_CALLBACK) {\r
+ continue;\r
+ }\r
+\r
+ //\r
+ // Check whether Statement is disabled.\r
+ //\r
+ if (Statement->Expression != NULL) {\r
+ if (EvaluateExpressionList(Statement->Expression, TRUE, Selection->FormSet, Selection->Form) == ExpressDisable) {\r
+ continue;\r
+ }\r
+ }\r
+\r
+ HiiValue = &Statement->HiiValue;\r
+ TypeValue = &HiiValue->Value;\r
+ if (HiiValue->Type == EFI_IFR_TYPE_BUFFER) {\r
+ //\r
+ // For OrderedList, passing in the value buffer to Callback()\r
+ //\r
+ TypeValue = (EFI_IFR_TYPE_VALUE *) Statement->BufferValue;\r
+ }\r
+ \r
+ ActionRequest = EFI_BROWSER_ACTION_REQUEST_NONE;\r
+ Status = ConfigAccess->Callback (\r
+ ConfigAccess,\r
+ Action,\r
+ Statement->QuestionId,\r
+ HiiValue->Type,\r
+ TypeValue,\r
+ &ActionRequest\r
+ );\r
+ if (!EFI_ERROR (Status)) {\r
+ //\r
+ // Only for EFI_BROWSER_ACTION_CHANGED need to handle this ActionRequest.\r
+ //\r
+ if (Action == EFI_BROWSER_ACTION_CHANGED) {\r
+ switch (ActionRequest) {\r
+ case EFI_BROWSER_ACTION_REQUEST_RESET:\r
+ gResetRequired = TRUE;\r
+ Selection->Action = UI_ACTION_EXIT;\r
+ break;\r
+\r
+ case EFI_BROWSER_ACTION_REQUEST_SUBMIT:\r
+ SubmitFormIsRequired = TRUE;\r
+ Selection->Action = UI_ACTION_EXIT;\r
+ break;\r
+\r
+ case EFI_BROWSER_ACTION_REQUEST_EXIT:\r
+ Selection->Action = UI_ACTION_EXIT;\r
+ break;\r
+\r
+ case EFI_BROWSER_ACTION_REQUEST_FORM_SUBMIT_EXIT:\r
+ SubmitFormIsRequired = TRUE;\r
+ SettingLevel = FormLevel;\r
+ NeedExit = TRUE;\r
+ break;\r
+\r
+ case EFI_BROWSER_ACTION_REQUEST_FORM_DISCARD_EXIT:\r
+ DiscardFormIsRequired = TRUE;\r
+ SettingLevel = FormLevel; \r
+ NeedExit = TRUE;\r
+ break;\r
+\r
+ case EFI_BROWSER_ACTION_REQUEST_FORM_APPLY:\r
+ SubmitFormIsRequired = TRUE;\r
+ SettingLevel = FormLevel;\r
+ break;\r
+\r
+ case EFI_BROWSER_ACTION_REQUEST_FORM_DISCARD:\r
+ DiscardFormIsRequired = TRUE;\r
+ SettingLevel = FormLevel;\r
+ break;\r
+\r
+ default:\r
+ break;\r
+ }\r
+ }\r
+\r
+ //\r
+ // According the spec, return value from call back of "changing" and \r
+ // "retrieve" should update to the question's temp buffer.\r
+ //\r
+ if (Action == EFI_BROWSER_ACTION_CHANGING || Action == EFI_BROWSER_ACTION_RETRIEVE) {\r
+ SetQuestionValue(Selection->FormSet, Selection->Form, Statement, GetSetValueWithEditBuffer);\r
+ }\r
+ } else {\r
+ //\r
+ // According the spec, return fail from call back of "changing" and \r
+ // "retrieve", should restore the question's value.\r
+ //\r
+ if (Action == EFI_BROWSER_ACTION_CHANGING || Action == EFI_BROWSER_ACTION_RETRIEVE) {\r
+ GetQuestionValue(Selection->FormSet, Selection->Form, Statement, GetSetValueWithEditBuffer);\r
+ }\r
+\r
+ if (Status == EFI_UNSUPPORTED) {\r
+ //\r
+ // If return EFI_UNSUPPORTED, also consider Hii driver suceess deal with it.\r
+ //\r
+ Status = EFI_SUCCESS;\r
+ }\r
+ }\r
+ }\r
+\r
+ if (SubmitFormIsRequired && !SkipSaveOrDiscard) {\r
+ SubmitForm (Selection->FormSet, Selection->Form, SettingLevel);\r
+ }\r
+\r
+ if (DiscardFormIsRequired && !SkipSaveOrDiscard) {\r
+ DiscardForm (Selection->FormSet, Selection->Form, SettingLevel);\r
+ }\r
+\r
+ if (NeedExit) {\r
+ FindNextMenu (Selection, NULL, NULL);\r
+ }\r
+\r
+ return Status;\r
+}\r
+\r
+/**\r
+ Call the retrieve type call back function for one question to get the initialize data.\r
+ \r
+ This function only used when in the initialize stage, because in this stage, the \r
+ Selection->Form is not ready. For other case, use the ProcessCallBackFunction instead.\r
+\r
+ @param ConfigAccess The config access protocol produced by the hii driver.\r
+ @param Statement The Question which need to call.\r
+\r
+ @retval EFI_SUCCESS The call back function excutes successfully.\r
+ @return Other value if the call back function failed to excute. \r
+**/\r
+EFI_STATUS \r
+ProcessRetrieveForQuestion (\r
+ IN EFI_HII_CONFIG_ACCESS_PROTOCOL *ConfigAccess,\r
+ IN FORM_BROWSER_STATEMENT *Statement\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ EFI_BROWSER_ACTION_REQUEST ActionRequest;\r
+ EFI_HII_VALUE *HiiValue;\r
+ EFI_IFR_TYPE_VALUE *TypeValue;\r
+\r
+ Status = EFI_SUCCESS;\r
+ ActionRequest = EFI_BROWSER_ACTION_REQUEST_NONE;\r
+ \r
+ if ((Statement->QuestionFlags & EFI_IFR_FLAG_CALLBACK) != EFI_IFR_FLAG_CALLBACK) {\r
+ return EFI_UNSUPPORTED;\r
+ }\r
+\r
+ HiiValue = &Statement->HiiValue;\r
+ TypeValue = &HiiValue->Value;\r
+ if (HiiValue->Type == EFI_IFR_TYPE_BUFFER) {\r
+ //\r
+ // For OrderedList, passing in the value buffer to Callback()\r
+ //\r
+ TypeValue = (EFI_IFR_TYPE_VALUE *) Statement->BufferValue;\r
+ }\r
+ \r
+ ActionRequest = EFI_BROWSER_ACTION_REQUEST_NONE;\r
+ Status = ConfigAccess->Callback (\r
+ ConfigAccess,\r
+ EFI_BROWSER_ACTION_RETRIEVE,\r
+ Statement->QuestionId,\r
+ HiiValue->Type,\r
+ TypeValue,\r
+ &ActionRequest\r
+ );\r
+ return Status;\r
+}\r
+\r
+/**\r
+ The worker function that send the displays to the screen. On output,\r
+ the selection made by user is returned.\r
+\r
+ @param Selection On input, Selection tell setup browser the information\r
+ about the Selection, form and formset to be displayed.\r
+ On output, Selection return the screen item that is selected\r
+ by user.\r
+\r
+ @retval EFI_SUCCESS The page is displayed successfully.\r
+ @return Other value if the page failed to be diplayed.\r
+\r
+**/\r
+EFI_STATUS\r
+SetupBrowser (\r
+ IN OUT UI_MENU_SELECTION *Selection\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ LIST_ENTRY *Link;\r
+ EFI_HANDLE NotifyHandle;\r
+ FORM_BROWSER_STATEMENT *Statement;\r
+ EFI_HII_CONFIG_ACCESS_PROTOCOL *ConfigAccess;\r
+ EFI_INPUT_KEY Key;\r
+\r
+ gMenuRefreshHead = NULL;\r
+ ConfigAccess = Selection->FormSet->ConfigAccess;\r
+\r
+ //\r
+ // Register notify for Form package update\r
+ //\r
+ Status = mHiiDatabase->RegisterPackageNotify (\r
+ mHiiDatabase,\r
+ EFI_HII_PACKAGE_FORMS,\r
+ NULL,\r
+ FormUpdateNotify,\r
+ EFI_HII_DATABASE_NOTIFY_REMOVE_PACK,\r
+ &NotifyHandle\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ //\r
+ // Initialize current settings of Questions in this FormSet\r
+ //\r
+ Status = InitializeCurrentSetting (Selection->FormSet);\r
+ if (EFI_ERROR (Status)) {\r
+ goto Done;\r
+ }\r
+\r
+ //\r
+ // Update gOldFormSet on maintain back up FormSet list.\r
+ // And, make gOldFormSet point to current FormSet. \r
+ //\r
+ if (gOldFormSet != NULL) {\r
+ RemoveEntryList (&gOldFormSet->Link);\r
+ DestroyFormSet (gOldFormSet);\r
+ }\r
+ gOldFormSet = Selection->FormSet;\r
+ InsertTailList (&gBrowserFormSetList, &gOldFormSet->Link);\r
+\r
+ do {\r
+ //\r
+ // IFR is updated, force to reparse the IFR binary\r
+ //\r
+ if (mHiiPackageListUpdated) {\r
+ Selection->Action = UI_ACTION_REFRESH_FORMSET;\r
+ mHiiPackageListUpdated = FALSE;\r
+ break;\r
+ }\r
+\r
+ //\r
+ // Initialize Selection->Form\r
+ //\r
+ if (Selection->FormId == 0) {\r
+ //\r
+ // Zero FormId indicates display the first Form in a FormSet\r
+ //\r
+ Link = GetFirstNode (&Selection->FormSet->FormListHead);\r
+\r
+ Selection->Form = FORM_BROWSER_FORM_FROM_LINK (Link);\r
+ Selection->FormId = Selection->Form->FormId;\r
+ } else {\r
+ Selection->Form = IdToForm (Selection->FormSet, Selection->FormId);\r
+ }\r
+\r
+ if (Selection->Form == NULL) {\r
+ //\r
+ // No Form to display\r
+ //\r
+ Status = EFI_NOT_FOUND;\r
+ goto Done;\r
+ }\r
+\r
+ //\r
+ // Check Form is suppressed.\r
+ //\r
+ if (Selection->Form->SuppressExpression != NULL) {\r
+ if (EvaluateExpressionList(Selection->Form->SuppressExpression, TRUE, Selection->FormSet, Selection->Form) == ExpressSuppress) {\r
+ //\r
+ // Form is suppressed. \r
+ //\r
+ do {\r
+ CreateDialog (4, TRUE, 0, NULL, &Key, gEmptyString, gFormSuppress, gPressEnter, gEmptyString);\r
+ } while (Key.UnicodeChar != CHAR_CARRIAGE_RETURN);\r
+\r
+ Status = EFI_NOT_FOUND;\r
+ goto Done;\r
+ }\r
+ }\r
+\r
+ //\r
+ // Before display new form, invoke ConfigAccess.Callback() with EFI_BROWSER_ACTION_FORM_OPEN\r
+ // for each question with callback flag.\r
+ // New form may be the first form, or the different form after another form close.\r
+ //\r
+ if ((ConfigAccess != NULL) &&\r
+ ((Selection->Handle != mCurrentHiiHandle) ||\r
+ (!CompareGuid (&Selection->FormSetGuid, &mCurrentFormSetGuid)) ||\r
+ (Selection->FormId != mCurrentFormId))) {\r
+\r
+ //\r
+ // Keep current form information\r
+ //\r
+ mCurrentHiiHandle = Selection->Handle;\r
+ CopyGuid (&mCurrentFormSetGuid, &Selection->FormSetGuid);\r
+ mCurrentFormId = Selection->FormId;\r
+\r
+ Status = ProcessCallBackFunction (Selection, NULL, EFI_BROWSER_ACTION_FORM_OPEN, FALSE);\r
+ if (EFI_ERROR (Status)) {\r
+ goto Done;\r
+ }\r
+\r
+ //\r
+ // EXIT requests to close form.\r
+ //\r
+ if (Selection->Action == UI_ACTION_EXIT) {\r
+ goto Done;\r
+ }\r
+ //\r
+ // IFR is updated during callback of open form, force to reparse the IFR binary\r
+ //\r
+ if (mHiiPackageListUpdated) {\r
+ Selection->Action = UI_ACTION_REFRESH_FORMSET;\r
+ mHiiPackageListUpdated = FALSE;\r
+ break;\r
+ }\r
+ }\r
+\r
+ //\r
+ // Load Questions' Value for display\r
+ //\r
+ Status = LoadFormSetConfig (Selection, Selection->FormSet);\r
+ if (EFI_ERROR (Status)) {\r
+ goto Done;\r
+ }\r
+\r
+ //\r
+ // EXIT requests to close form.\r
+ //\r
+ if (Selection->Action == UI_ACTION_EXIT) {\r
+ goto Done;\r
+ }\r
+ //\r
+ // IFR is updated during callback of read value, force to reparse the IFR binary\r
+ //\r
+ if (mHiiPackageListUpdated) {\r
+ Selection->Action = UI_ACTION_REFRESH_FORMSET;\r
+ mHiiPackageListUpdated = FALSE;\r
+ break;\r
+ }\r
+\r
+ //\r
+ // Displays the Header and Footer borders\r
+ //\r
+ DisplayPageFrame (Selection);\r
+\r
+ //\r
+ // Display form\r
+ //\r
+ Status = DisplayForm (Selection);\r
+ if (EFI_ERROR (Status)) {\r
+ goto Done;\r
+ }\r
+\r
+ //\r
+ // Check Selected Statement (if press ESC, Selection->Statement will be NULL)\r
+ //\r
+ Statement = Selection->Statement;\r
+ if (Statement != NULL) {\r
+ if ((Statement->QuestionFlags & EFI_IFR_FLAG_RESET_REQUIRED) == EFI_IFR_FLAG_RESET_REQUIRED) {\r
+ gResetRequired = TRUE;\r
+ }\r
+\r
+ if ((ConfigAccess != NULL) && \r
+ ((Statement->QuestionFlags & EFI_IFR_FLAG_CALLBACK) == EFI_IFR_FLAG_CALLBACK) && \r
+ (Statement->Operand != EFI_IFR_PASSWORD_OP)) {\r
+ Status = ProcessCallBackFunction(Selection, Statement, EFI_BROWSER_ACTION_CHANGING, FALSE); \r
+ if (Statement->Operand == EFI_IFR_REF_OP && Selection->Action != UI_ACTION_EXIT) {\r
+ //\r
+ // Process dynamic update ref opcode.\r
+ //\r
+ if (!EFI_ERROR (Status)) {\r
+ Status = ProcessGotoOpCode(Statement, Selection, NULL, NULL);\r
+ }\r
+ \r
+ //\r
+ // Callback return error status or status return from process goto opcode.\r
+ //\r
+ if (EFI_ERROR (Status)) {\r
+ //\r
+ // Cross reference will not be taken\r
+ //\r
+ Selection->FormId = Selection->Form->FormId;\r
+ Selection->QuestionId = 0;\r
+ }\r
+ }\r
+\r
+ if (!EFI_ERROR (Status) && Statement->Operand != EFI_IFR_REF_OP) {\r
+ ProcessCallBackFunction(Selection, Statement, EFI_BROWSER_ACTION_CHANGED, FALSE);\r
+ }\r
+ }\r
+ }\r
+\r
+ //\r
+ // Before exit the form, invoke ConfigAccess.Callback() with EFI_BROWSER_ACTION_FORM_CLOSE\r
+ // for each question with callback flag.\r
+ //\r
+ if ((ConfigAccess != NULL) && \r
+ ((Selection->Action == UI_ACTION_EXIT) || \r
+ (Selection->Handle != mCurrentHiiHandle) ||\r
+ (!CompareGuid (&Selection->FormSetGuid, &mCurrentFormSetGuid)) ||\r
+ (Selection->FormId != mCurrentFormId))) {\r
+\r
+ Status = ProcessCallBackFunction (Selection, NULL, EFI_BROWSER_ACTION_FORM_CLOSE, FALSE);\r
+ if (EFI_ERROR (Status)) {\r
+ goto Done;\r
+ }\r
+ }\r
+ } while (Selection->Action == UI_ACTION_REFRESH_FORM);\r
+\r
+Done:\r
+ //\r
+ // Reset current form information to the initial setting when error happens or form exit.\r
+ //\r
+ if (EFI_ERROR (Status) || Selection->Action == UI_ACTION_EXIT) {\r
+ mCurrentHiiHandle = NULL;\r
+ CopyGuid (&mCurrentFormSetGuid, &gZeroGuid);\r
+ mCurrentFormId = 0;\r
+ }\r
+\r
+ //\r
+ // Unregister notify for Form package update\r
+ //\r
+ mHiiDatabase->UnregisterPackageNotify (\r
+ mHiiDatabase,\r
+ NotifyHandle\r
+ );\r
+ return Status;\r
+}\r