summaryrefslogtreecommitdiff
path: root/EdkModulePkg/Universal/UserInterface/SetupBrowser/Dxe/Presentation.c
diff options
context:
space:
mode:
Diffstat (limited to 'EdkModulePkg/Universal/UserInterface/SetupBrowser/Dxe/Presentation.c')
-rw-r--r--EdkModulePkg/Universal/UserInterface/SetupBrowser/Dxe/Presentation.c1481
1 files changed, 1481 insertions, 0 deletions
diff --git a/EdkModulePkg/Universal/UserInterface/SetupBrowser/Dxe/Presentation.c b/EdkModulePkg/Universal/UserInterface/SetupBrowser/Dxe/Presentation.c
new file mode 100644
index 0000000..cf3d000
--- /dev/null
+++ b/EdkModulePkg/Universal/UserInterface/SetupBrowser/Dxe/Presentation.c
@@ -0,0 +1,1481 @@
+/*++
+Copyright (c) 2006, 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.
+
+Revision History:
+
+--*/
+
+#include "Setup.h"
+#include "Ui.h"
+#include "Colors.h"
+
+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] = (CHAR16) 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;
+ EFI_SCREEN_DESCRIPTOR LocalScreen;
+ UINTN Row;
+
+ 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 = (CHAR16) 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 = (CHAR16) BOXDRAW_DOWN_RIGHT;
+
+ PrintChar (Character);
+ PrintString (Buffer);
+
+ Character = (CHAR16) BOXDRAW_DOWN_LEFT;
+ PrintChar (Character);
+
+ Character = (CHAR16) 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 = (CHAR16) BOXDRAW_UP_RIGHT;
+ PrintCharAt (LocalScreen.LeftColumn, LocalScreen.TopRow + NONE_FRONT_PAGE_HEADER_HEIGHT - 1, Character);
+ PrintString (Buffer);
+
+ Character = (CHAR16) BOXDRAW_UP_LEFT;
+ PrintChar (Character);
+
+ if (gClassOfVfr == EFI_SETUP_APPLICATION_SUBCLASS) {
+ //
+ // Print Bottom border line
+ // +------------------------------------------------------------------------------+
+ // ? ?
+ // +------------------------------------------------------------------------------+
+ //
+ Character = (CHAR16) BOXDRAW_DOWN_RIGHT;
+ PrintCharAt (LocalScreen.LeftColumn, LocalScreen.BottomRow - STATUS_BAR_HEIGHT - FOOTER_HEIGHT, Character);
+
+ PrintString (Buffer);
+
+ Character = (CHAR16) BOXDRAW_DOWN_LEFT;
+ PrintChar (Character);
+ Character = (CHAR16) 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 = (CHAR16) BOXDRAW_UP_RIGHT;
+ PrintCharAt (LocalScreen.LeftColumn, LocalScreen.BottomRow - STATUS_BAR_HEIGHT - 1, Character);
+
+ PrintString (Buffer);
+
+ Character = (CHAR16) BOXDRAW_UP_LEFT;
+ PrintChar (Character);
+ }
+ }
+
+ gBS->FreePool (Buffer);
+
+}
+
+/*
++------------------------------------------------------------------------------+
+?F2=Previous Page Setup Page ?
++------------------------------------------------------------------------------+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
++------------------------------------------------------------------------------+
+?F1=Scroll Help F9=Reset to Defaults F10=Save and Exit ?
+| ^"=Move Highlight <Spacebar> Toggles Checkbox Esc=Discard Changes |
++------------------------------------------------------------------------------+
+*/
+UI_MENU_OPTION *
+DisplayForm (
+ OUT UI_MENU_OPTION *Selection,
+ IN UINT16 FormHandle,
+ IN UINT16 TitleToken,
+ IN EFI_FORM_TAGS FormTags,
+ IN EFI_FILE_FORM_TAGS *FileFormTagsHead,
+ IN UINT8 *CallbackData
+ )
+{
+ CHAR16 *StringPtr;
+ UINTN Index;
+ UINTN Count;
+ UINT16 MenuItemCount;
+ EFI_HII_HANDLE Handle;
+ UINT16 FormId;
+ STRING_REF String;
+ EFI_FILE_FORM_TAGS *FileFormTags;
+ BOOLEAN SuppressIf;
+ BOOLEAN Suppress;
+ BOOLEAN GrayOut;
+ BOOLEAN Conditional;
+ EFI_SCREEN_DESCRIPTOR LocalScreen;
+ UINT16 Width;
+ UINTN ArrayEntry;
+ CHAR16 *OutputString;
+
+ Handle = Selection->Handle;
+ FormId = 0;
+ String = 0;
+ MenuItemCount = 0;
+ ArrayEntry = 0;
+ OutputString = NULL;
+
+ CopyMem (&LocalScreen, &gScreenDimensions, sizeof (EFI_SCREEN_DESCRIPTOR));
+
+ //
+ // If we hit a F2 (previous) we already nuked the menu and are simply carrying around what information we need
+ //
+ if (Selection->Previous) {
+ Selection->Previous = FALSE;
+ } else {
+ UiFreeMenu ();
+ UiInitMenu ();
+ }
+
+ StringPtr = GetToken (TitleToken, 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, (CHAR16 *) 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);
+
+ for (Index = 0; FormTags.Tags[Index].Operand != EFI_IFR_END_FORM_OP; Index++) {
+ GrayOut = FALSE;
+ Suppress = FALSE;
+ SuppressIf = FALSE;
+ Conditional = FALSE;
+ FileFormTags = FileFormTagsHead;
+
+ if (FormTags.Tags[Index].Operand == EFI_IFR_FORM_OP) {
+ FormId = FormTags.Tags[Index].Id;
+ }
+ //
+ // This gives us visibility to the FileFormTags->NvRamMap to check things
+ // ActiveIfr is a global maintained by the menuing code to ensure that we
+ // are pointing to the correct formset's file data.
+ //
+ for (Count = 0; Count < gActiveIfr; Count++) {
+ FileFormTags = FileFormTags->NextFile;
+ }
+ //
+ // GrayoutIf [SuppressIf]
+ // <BOOLEANS>
+ // OpCode(s)
+ // EndIf
+ //
+ // SuppressIf [GrayoutIf]
+ // <BOOLEANS>
+ // OpCode(s)
+ // EndIf
+ //
+ Count = 0;
+
+ do {
+ switch (FormTags.Tags[Index].Operand) {
+ case EFI_IFR_SUPPRESS_IF_OP:
+ SuppressIf = TRUE;
+
+ case EFI_IFR_GRAYOUT_IF_OP:
+
+ Conditional = TRUE;
+
+ //
+ // Advance to the next op-code
+ //
+ Index++;
+
+ //
+ // We are now pointing to the beginning of the consistency checking. Let's fast forward
+ // through the AND/OR/NOT data to come up with some meaningful ID data.
+ //
+ for (;
+ FormTags.Tags[Index].Operand == EFI_IFR_AND_OP ||
+ FormTags.Tags[Index].Operand == EFI_IFR_OR_OP ||
+ FormTags.Tags[Index].Operand == EFI_IFR_GT_OP ||
+ FormTags.Tags[Index].Operand == EFI_IFR_GE_OP ||
+ FormTags.Tags[Index].Operand == EFI_IFR_NOT_OP;
+ Index++
+ )
+ ;
+
+ //
+ // We need to walk through the consistency checks until we hit the end of the consistency
+ // FALSE means evaluate this single expression
+ // The ConsistencyId refers to which expression in the Consistency database to use
+ //
+ if (SuppressIf) {
+ Suppress = ValueIsNotValid (
+ FALSE,
+ FormTags.Tags[Index].ConsistencyId,
+ &FormTags.Tags[Index],
+ FileFormTags,
+ &String
+ );
+ SuppressIf = FALSE;
+ } else {
+ GrayOut = ValueIsNotValid (
+ FALSE,
+ FormTags.Tags[Index].ConsistencyId,
+ &FormTags.Tags[Index],
+ FileFormTags,
+ &String
+ );
+ }
+ //
+ // Advance to the end of the expression (Will land us at a grayoutif/suppressif or the op-code being affected)
+ //
+ for (;
+ FormTags.Tags[Index].Operand == EFI_IFR_EQ_ID_VAL_OP ||
+ FormTags.Tags[Index].Operand == EFI_IFR_EQ_VAR_VAL_OP ||
+ FormTags.Tags[Index].Operand == EFI_IFR_EQ_ID_ID_OP ||
+ FormTags.Tags[Index].Operand == EFI_IFR_EQ_ID_LIST_OP ||
+ FormTags.Tags[Index].Operand == EFI_IFR_NOT_OP ||
+ FormTags.Tags[Index].Operand == EFI_IFR_AND_OP ||
+ FormTags.Tags[Index].Operand == EFI_IFR_OR_OP ||
+ FormTags.Tags[Index].Operand == EFI_IFR_TRUE_OP ||
+ FormTags.Tags[Index].Operand == EFI_IFR_FALSE_OP ||
+ FormTags.Tags[Index].Operand == EFI_IFR_GT_OP ||
+ FormTags.Tags[Index].Operand == EFI_IFR_GE_OP ||
+ FormTags.Tags[Index].Operand == EFI_IFR_LABEL_OP;
+ Index++
+ )
+ ;
+ break;
+
+ default:
+ goto GetOut;
+ }
+ //
+ // Do this two times (at most will see a suppress and grayout combination
+ //
+ Count++;
+ } while (Count < 2);
+
+GetOut:
+ do {
+ if (GrayOut) {
+ FormTags.Tags[Index].GrayOut = TRUE;
+ } else {
+ FormTags.Tags[Index].GrayOut = FALSE;
+ }
+ if (Suppress && FormTags.Tags[Index].Operand == EFI_IFR_ONE_OF_OPTION_OP) {
+ //
+ // Only need .Suppress field when the tag is a one_of_option. For other cases, omit them directly.
+ //
+ FormTags.Tags[Index].Suppress = TRUE;
+ } else {
+ FormTags.Tags[Index].Suppress = FALSE;
+ }
+
+ if ((
+ FormTags.Tags[Index].NumberOfLines > 0 ||
+ FormTags.Tags[Index].Operand == EFI_IFR_DATE_OP ||
+ FormTags.Tags[Index].Operand == EFI_IFR_TIME_OP
+ ) &&
+ !Suppress
+ ) {
+
+ StringPtr = GetToken (FormTags.Tags[Index].Text, Handle);
+
+ Width = GetWidth (&FormTags.Tags[Index], Handle);
+
+ //
+ // This data can be retrieved over and over again. Therefore, reset to original values
+ // before processing otherwise things will start growing linearly
+ //
+ if (FormTags.Tags[Index].NumberOfLines > 1) {
+ FormTags.Tags[Index].NumberOfLines = 1;
+ }
+
+ for (Count = 0; 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])) {
+ FormTags.Tags[Index].NumberOfLines++;
+ }
+
+ gBS->FreePool (OutputString);
+ }
+
+ ArrayEntry = 0;
+
+ //
+ // We are NOT!! removing this StringPtr buffer via FreePool since it is being used in the menuoptions, we will do
+ // it in UiFreeMenu.
+ //
+ UiAddSubMenuOption (StringPtr, Handle, FormTags.Tags, Index, FormId, MenuItemCount);
+ MenuItemCount++;
+ }
+ //
+ // Keep processing menu entries based on the resultant suppress/grayout results until we hit an end-if
+ //
+ Index++;
+ } while (FormTags.Tags[Index].Operand != EFI_IFR_END_IF_OP && Conditional);
+
+ //
+ // We advanced the index for the above conditional, rewind it to keep harmony with the for loop logic
+ //
+ Index--;
+ }
+
+ Selection = UiDisplayMenu (TRUE, FileFormTagsHead, (EFI_IFR_DATA_ARRAY *) CallbackData);
+
+ return Selection;
+}
+
+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);
+ gMoveHighlight = GetToken (STRING_TOKEN (MOVE_HIGHLIGHT), gHiiHandle);
+ gMakeSelection = GetToken (STRING_TOKEN (MAKE_SELECTION), gHiiHandle);
+ gNumericInput = GetToken (STRING_TOKEN (NUMERIC_INPUT), gHiiHandle);
+ gToggleCheckBox = GetToken (STRING_TOKEN (TOGGLE_CHECK_BOX), 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);
+ 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
+UpdateKeyHelp (
+ IN UI_MENU_OPTION *Selection,
+ IN BOOLEAN Selected
+ )
+/*++
+Routine Description:
+ Update key's help imformation
+
+Arguments:
+ Selection C The form that current display
+ Selected C Whether or not a tag be selected
+
+Returns:
+ None
+--*/
+{
+ UINTN SecCol;
+ UINTN ThdCol;
+ UINTN LeftColumnOfHelp;
+ UINTN RightColumnOfHelp;
+ UINTN TopRowOfHelp;
+ UINTN BottomRowOfHelp;
+ UINTN StartColumnOfHelp;
+ EFI_SCREEN_DESCRIPTOR LocalScreen;
+
+ 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);
+
+ switch (Selection->ThisTag->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 ((Selection->ThisTag->Operand == EFI_IFR_DATE_OP) || (Selection->ThisTag->Operand == EFI_IFR_TIME_OP)) {
+ PrintAt (
+ StartColumnOfHelp,
+ BottomRowOfHelp,
+ (CHAR16 *) L"%c%c%c%c%s",
+ ARROW_UP,
+ ARROW_DOWN,
+ ARROW_RIGHT,
+ ARROW_LEFT,
+ gMoveHighlight
+ );
+ PrintStringAt (SecCol, BottomRowOfHelp, gAdjustNumber);
+ } else {
+ PrintAt (StartColumnOfHelp, BottomRowOfHelp, (CHAR16 *) L"%c%c%s", ARROW_UP, ARROW_DOWN, gMoveHighlight);
+ PrintStringAt (SecCol, BottomRowOfHelp, gEnterString);
+ }
+ } else {
+ PrintStringAt (StartColumnOfHelp, BottomRowOfHelp, gEnterCommitString);
+
+ //
+ // If it is a selected numeric with manual input, display different message
+ //
+ if ((Selection->ThisTag->Operand == EFI_IFR_NUMERIC_OP) && (Selection->ThisTag->Step == 0)) {
+ PrintStringAt (SecCol, TopRowOfHelp, gNumericInput);
+ } else if (Selection->ThisTag->Operand != EFI_IFR_ORDERED_LIST_OP) {
+ PrintAt (SecCol, BottomRowOfHelp, (CHAR16 *) L"%c%c%s", ARROW_UP, ARROW_DOWN, gMoveHighlight);
+ }
+
+ if (Selection->ThisTag->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, (CHAR16 *) 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:
+ 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, (CHAR16 *) L"%c%c%s", ARROW_UP, ARROW_DOWN, gMoveHighlight);
+ PrintStringAt (SecCol, BottomRowOfHelp, gEnterString);
+ } else {
+ if (Selection->ThisTag->Operand != EFI_IFR_REF_OP) {
+ PrintStringAt (
+ (LocalScreen.RightColumn - GetStringWidth (gEnterCommitString) / 2) / 2,
+ BottomRowOfHelp,
+ gEnterCommitString
+ );
+ PrintStringAt (ThdCol, BottomRowOfHelp, gEscapeString);
+ }
+ }
+ break;
+ }
+
+}
+
+VOID
+ExtractFormHandle (
+ IN UI_MENU_OPTION *Selection,
+ IN EFI_FILE_FORM_TAGS *FileFormTagsHead,
+ IN UINTN IdValue,
+ OUT UINT16 *FormHandle,
+ OUT UINT16 *TitleToken,
+ OUT EFI_FORM_TAGS *FormTags
+ )
+{
+ UINTN Index;
+ EFI_FILE_FORM_TAGS *FileFormTags;
+ EFI_FORM_TAGS LocalTags;
+
+ FileFormTags = FileFormTagsHead;
+
+ //
+ // Advance FileFormTags to the correct file's tag information.
+ // For instance, if Selection->IfrNumber is 3, that means the 4th
+ // file (0-based) in the FileFormTags linked-list contains the tag
+ // information.
+ //
+ for (Index = 0; Index < Selection->IfrNumber; Index++) {
+ FileFormTags = FileFormTags->NextFile;
+ }
+
+ LocalTags = FileFormTags->FormTags;
+
+ if (IdValue == 0) {
+ //
+ // Advance Index to the first FormOp tag information
+ //
+ for (Index = 0; FileFormTags->FormTags.Tags[Index].Operand != EFI_IFR_FORM_OP; Index++)
+ ;
+ } else {
+ //
+ // Advance Index to the FormOp with the correct ID value
+ //
+ for (; LocalTags.Next != NULL; LocalTags = *LocalTags.Next) {
+ for (Index = 0; LocalTags.Tags[Index].Operand != EFI_IFR_FORM_OP; Index++)
+ ;
+ if (LocalTags.Tags[Index].Id == IdValue) {
+ break;
+ }
+ }
+ }
+ //
+ // return the Form Id, Text, and the File's FormTags structure
+ //
+ *FormHandle = LocalTags.Tags[Index].Id;
+ *TitleToken = LocalTags.Tags[Index].Text;
+ *FormTags = LocalTags;
+ return ;
+}
+
+EFI_STATUS
+UpdateNewTagData (
+ IN UINT8 *FormData,
+ IN UINT16 ConsistencyId,
+ IN UINT16 CurrentVariable,
+ IN EFI_FORM_TAGS *FormTags,
+ OUT EFI_FILE_FORM_TAGS *FileFormTags
+ )
+{
+ EFI_STATUS Status;
+ UINT16 Index;
+ UINT16 QuestionIndex;
+ UINT16 NumberOfTags;
+ INT16 CurrTag;
+ UINT8 TagLength;
+ UINTN Count;
+ BOOLEAN Finished;
+
+ //
+ // Initialize some Index variable and Status
+ //
+ Count = 0;
+ QuestionIndex = 0;
+ NumberOfTags = 1;
+ Index = 0;
+ Status = EFI_SUCCESS;
+ Finished = FALSE;
+
+ //
+ // Determine the number of tags for the first form
+ //
+ GetTagCount (&FormData[Index], &NumberOfTags);
+
+ //
+ // Allocate memory for our tags on the first form
+ //
+ FormTags->Tags = AllocateZeroPool (NumberOfTags * sizeof (EFI_TAG));
+ ASSERT (FormTags->Tags != NULL);
+
+ for (CurrTag = 0; FormData[Index] != EFI_IFR_END_FORM_SET_OP; CurrTag++) {
+ //
+ // Operand = IFR OpCode
+ //
+ FormTags->Tags[CurrTag].Operand = FormData[Index];
+
+ //
+ // Assume for now 0 lines occupied by this OpCode
+ //
+ FormTags->Tags[CurrTag].NumberOfLines = 0;
+
+ //
+ // Determine the length of the Tag so we can later skip to the next tag in the form
+ //
+ //
+ // get the length
+ //
+ TagLength = FormData[Index + 1];
+ //
+ // Operate on the Found OpCode
+ //
+ switch (FormData[Index]) {
+
+ case EFI_IFR_FORM_OP:
+ case EFI_IFR_SUBTITLE_OP:
+ case EFI_IFR_TEXT_OP:
+ case EFI_IFR_REF_OP:
+ IfrToFormTag (FormData[Index], &FormTags->Tags[CurrTag], (VOID *) &FormData[Index], NULL);
+ break;
+
+ case EFI_IFR_VARSTORE_SELECT_OP:
+ IfrToFormTag (FormData[Index], &FormTags->Tags[CurrTag], (VOID *) &FormData[Index], NULL);
+ CopyMem (&CurrentVariable, &((EFI_IFR_VARSTORE_SELECT *) &FormData[Index])->VarId, sizeof (UINT16));
+ break;
+
+ case EFI_IFR_END_FORM_OP:
+ FormTags->Tags[CurrTag].Operand = FormData[Index];
+ FormTags->Tags[CurrTag].NumberOfLines = 0;
+
+ Finished = TRUE;
+ break;
+
+ case EFI_IFR_ORDERED_LIST_OP:
+ case EFI_IFR_ONE_OF_OP:
+ GetQuestionHeader (&FormTags->Tags[CurrTag], FormData, Index, FileFormTags, CurrentVariable);
+
+ //
+ // Store away the CurrTag since what follows will be the answer that we
+ // need to place into the appropriate location in the tag array
+ //
+ //
+ // record for setting default later
+ //
+ QuestionIndex = (UINT16) CurrTag;
+ break;
+
+ case EFI_IFR_ONE_OF_OPTION_OP:
+ IfrToFormTag (FormData[Index], &FormTags->Tags[CurrTag], (VOID *) &FormData[Index], NULL);
+ FormTags->Tags[QuestionIndex].Key = ((EFI_IFR_ONE_OF_OPTION *) &FormData[Index])->Key;
+ FormTags->Tags[QuestionIndex].ResetRequired = (BOOLEAN) (FormTags->Tags[QuestionIndex].Flags & EFI_IFR_FLAG_RESET_REQUIRED);
+ break;
+
+ case EFI_IFR_CHECKBOX_OP:
+ GetQuestionHeader (&FormTags->Tags[CurrTag], FormData, Index, FileFormTags, CurrentVariable);
+ IfrToFormTag (FormData[Index], &FormTags->Tags[CurrTag], (VOID *) &FormData[Index], NULL);
+ break;
+
+ case EFI_IFR_NUMERIC_OP:
+ GetNumericHeader (&FormTags->Tags[CurrTag], FormData, Index, (UINT16) 1, FileFormTags, CurrentVariable);
+ IfrToFormTag (FormData[Index], &FormTags->Tags[CurrTag], (VOID *) &FormData[Index], NULL);
+ break;
+
+ case EFI_IFR_DATE_OP:
+ //
+ // Date elements come in as a Year, Month, Day. We need to process them as a country-based
+ // Order. It is much easier to do it here than anywhere else.
+ //
+ // For US standards - we want Month/Day/Year, thus we advance "i" +1, +2, +0 while CurrTag is +0, +1, +2
+ //
+ GetNumericHeader (
+ &FormTags->Tags[CurrTag],
+ FormData,
+ (UINT16) (Index + TagLength),
+ (UINT16) 0,
+ FileFormTags,
+ CurrentVariable
+ );
+
+ //
+ // The current language selected + the Date operand
+ //
+ FormTags->Tags[CurrTag + 1].Operand = FormData[Index];
+ GetNumericHeader (
+ &FormTags->Tags[CurrTag + 1],
+ FormData,
+ (UINT16) (Index + TagLength + FormData[Index + TagLength + 1]),
+ (UINT16) 0,
+ FileFormTags,
+ CurrentVariable
+ );
+
+ //
+ // The current language selected + the Date operand
+ //
+ FormTags->Tags[CurrTag + 2].Operand = FormData[Index];
+ GetNumericHeader (&FormTags->Tags[CurrTag + 2], FormData, Index, (UINT16) 1, FileFormTags, CurrentVariable);
+
+ CurrTag = (INT16) (CurrTag + 2);
+
+ Index = (UINT16) (Index + TagLength);
+ //
+ // get the length
+ //
+ TagLength = FormData[Index + 1];
+ Index = (UINT16) (Index + TagLength);
+ //
+ // get the length
+ //
+ TagLength = FormData[Index + 1];
+ break;
+
+ case EFI_IFR_TIME_OP:
+ GetNumericHeader (&FormTags->Tags[CurrTag], FormData, Index, (UINT16) 0, FileFormTags, CurrentVariable);
+
+ if (Count == 2) {
+ //
+ // Override the GetQuestionHeader information - date/time are treated very differently
+ //
+ FormTags->Tags[CurrTag].NumberOfLines = 1;
+ Count = 0;
+ } else {
+ //
+ // The premise is that every date/time op-code have 3 elements, the first 2 have 0 lines
+ // associated with them, and the third has 1 line to allow to space beyond the choice.
+ //
+ Count++;
+ }
+ break;
+
+ case EFI_IFR_PASSWORD_OP:
+ case EFI_IFR_STRING_OP:
+ GetQuestionHeader (&FormTags->Tags[CurrTag], FormData, Index, FileFormTags, CurrentVariable);
+ IfrToFormTag (FormData[Index], &FormTags->Tags[CurrTag], (VOID *) &FormData[Index], NULL);
+ break;
+
+ case EFI_IFR_INCONSISTENT_IF_OP:
+ case EFI_IFR_SUPPRESS_IF_OP:
+ case EFI_IFR_GRAYOUT_IF_OP:
+ ConsistencyId++;
+ break;
+
+ case EFI_IFR_EQ_ID_VAL_OP:
+ IfrToFormTag (FormData[Index], &FormTags->Tags[CurrTag], (VOID *) &FormData[Index], NULL);
+ FormTags->Tags[CurrTag].ConsistencyId = ConsistencyId;
+ break;
+
+ case EFI_IFR_EQ_VAR_VAL_OP:
+ IfrToFormTag (FormData[Index], &FormTags->Tags[CurrTag], (VOID *) &FormData[Index], NULL);
+ FormTags->Tags[CurrTag].ConsistencyId = ConsistencyId;
+ break;
+
+ case EFI_IFR_EQ_ID_ID_OP:
+ IfrToFormTag (FormData[Index], &FormTags->Tags[CurrTag], (VOID *) &FormData[Index], NULL);
+ FormTags->Tags[CurrTag].ConsistencyId = ConsistencyId;
+ break;
+
+ case EFI_IFR_AND_OP:
+ case EFI_IFR_OR_OP:
+ case EFI_IFR_NOT_OP:
+ case EFI_IFR_TRUE_OP:
+ case EFI_IFR_FALSE_OP:
+ case EFI_IFR_GT_OP:
+ case EFI_IFR_GE_OP:
+ FormTags->Tags[CurrTag].ConsistencyId = ConsistencyId;
+ break;
+
+ case EFI_IFR_EQ_ID_LIST_OP:
+ IfrToFormTag (FormData[Index], &FormTags->Tags[CurrTag], (VOID *) &FormData[Index], NULL);
+
+ FormTags->Tags[CurrTag].ConsistencyId = ConsistencyId;
+ break;
+
+ default:
+ break;
+ }
+ //
+ // End of switch
+ //
+ if (Finished) {
+ break;
+ }
+ //
+ // Per spec., we ignore ops that we don't know how to deal with. Skip to next tag
+ //
+ Index = (UINT16) (Index + TagLength);
+ }
+ //
+ // End of Index
+ //
+ return Status;
+}
+
+VOID
+ExtractDynamicFormHandle (
+ IN UI_MENU_OPTION *Selection,
+ IN UINT8 *CallbackData,
+ IN EFI_FILE_FORM_TAGS *FileFormTagsHead,
+ IN UINTN IdValue,
+ OUT UINT16 *FormHandle,
+ OUT UINT16 *TitleToken,
+ OUT EFI_FORM_TAGS *FormTags
+ )
+/*++
+
+Routine Description:
+
+ The function does the most of the works when the EFI_TAG that
+ user selects on is EFI_IFR_FLAG_INTERACTIVE or EFI_IFR_PASSWORD_OP:
+ invoke CallBack, update the new form data.
+
+Arguments:
+
+ Selection - The current selection of the form.
+ CallbackData - The pointer to host the data passed back by the callback function.
+ FileFormTagsHead - Prompt string token of the one-of box
+ IdValue - The current page number.
+ FormHandle - Output the the handle of the form.
+ TitleToken - Output the TitleToken of the new page.
+ FormTags - Output the FormFags of the new page.
+
+Returns:
+ VOID
+
+--*/
+{
+ UINTN Index;
+ UINTN BackupIndex;
+ EFI_FILE_FORM_TAGS *FileFormTags;
+ EFI_FORM_TAGS *LocalTags;
+ EFI_FORM_CALLBACK_PROTOCOL *FormCallback;
+ EFI_STATUS Status;
+ UINTN Length;
+ UINT8 *Buffer;
+ EFI_PHYSICAL_ADDRESS CallbackHandle;
+ EFI_GUID TagGuid;
+ UINT16 TargetPage;
+ EFI_HII_CALLBACK_PACKET *Packet;
+ UINTN ScreenSize;
+ CHAR16 NullCharacter;
+ EFI_INPUT_KEY Key;
+ UINT16 ConsistencyId;
+ UINT16 CurrentVariable;
+ EFI_VARIABLE_DEFINITION *VariableDefinition;
+ EFI_IFR_DATA_ENTRY *DataEntry;
+
+ VariableDefinition = NULL;
+ NullCharacter = CHAR_NULL;
+
+ CurrentVariable = 0;
+ FileFormTags = FileFormTagsHead;
+ Length = 0;
+ CallbackHandle = 0;
+ TargetPage = (UINT16) IdValue;
+ Packet = NULL;
+ ConsistencyId = 0;
+
+ //
+ // Advance FileFormTags to the correct file's tag information.
+ // For instance, if Selection->IfrNumber is 3, that means the 4th
+ // file (0-based) in the FileFormTags linked-list contains the tag
+ // information.
+ //
+ for (Index = 0; Index < Selection->IfrNumber; Index++) {
+ FileFormTags = FileFormTags->NextFile;
+ }
+
+ LocalTags = &FileFormTags->FormTags;
+
+ //
+ // Advance Index to the FormOp with the correct ID value
+ //
+ for (; LocalTags->Next != NULL; LocalTags = LocalTags->Next) {
+ if ((LocalTags->Tags[0].CallbackHandle != 0) && (CallbackHandle == 0)) {
+ CallbackHandle = LocalTags->Tags[0].CallbackHandle;
+ CopyMem (&TagGuid, &LocalTags->Tags[0].GuidValue, sizeof (EFI_GUID));
+ }
+
+ for (Index = 0; LocalTags->Tags[Index].Operand != EFI_IFR_FORM_OP; Index++)
+ ;
+ if (LocalTags->Tags[Index].Id == IdValue) {
+ break;
+ }
+ }
+ //
+ // If we are going to callback on a non-goto opcode, make sure we don't change pages
+ //
+ if (Selection->ThisTag->Operand != EFI_IFR_REF_OP) {
+ TargetPage = Selection->FormId;
+ }
+ //
+ // The first tag below should be the form op-code. We need to store away the
+ // current variable setting to ensure if we have to reload the page, that we
+ // can correctly restore the values for the active variable
+ //
+ CurrentVariable = Selection->Tags[0].VariableNumber;
+
+ //
+ // Remember that dynamic pages in an environment where all pages are not
+ // dynamic require us to call back to the user to give them an opportunity
+ // to register fresh information in the HII database so that we can extract it.
+ //
+ Status = gBS->HandleProtocol (
+ (VOID *) (UINTN) CallbackHandle,
+ &gEfiFormCallbackProtocolGuid,
+ (VOID **) &FormCallback
+ );
+
+ if (EFI_ERROR (Status)) {
+ gBS->FreePool (LocalTags->Tags);
+ return ;
+ }
+
+ ExtractRequestedNvMap (FileFormTags, CurrentVariable, &VariableDefinition);
+
+ if (Selection->ThisTag->Flags & (EFI_IFR_FLAG_INTERACTIVE | EFI_IFR_FLAG_NV_ACCESS)) {
+ ((EFI_IFR_DATA_ARRAY *) CallbackData)->NvRamMap = VariableDefinition->NvRamMap;
+ } else {
+ ((EFI_IFR_DATA_ARRAY *) CallbackData)->NvRamMap = NULL;
+ }
+
+ if ((FormCallback != NULL) && (FormCallback->Callback != NULL)) {
+ Status = FormCallback->Callback (
+ FormCallback,
+ Selection->ThisTag->Key,
+ (EFI_IFR_DATA_ARRAY *) CallbackData,
+ &Packet
+ );
+ }
+
+ if (EFI_ERROR (Status)) {
+ //
+ // Restore Previous Value
+ //
+ CopyMem (
+ &VariableDefinition->NvRamMap[Selection->ThisTag->StorageStart],
+ gPreviousValue,
+ Selection->ThisTag->StorageWidth
+ );
+
+ if (Packet != NULL) {
+ //
+ // Upon error, we will likely receive a string to print out
+ //
+ ScreenSize = GetStringWidth (Packet->String) / 2;
+
+ //
+ // Display error popup
+ //
+ CreatePopUp (ScreenSize, 3, &NullCharacter, Packet->String, &NullCharacter);
+
+ do {
+ Status = WaitForKeyStroke (&Key);
+ } while (Key.UnicodeChar != CHAR_CARRIAGE_RETURN);
+ } else {
+ UpdateStatusBar (INPUT_ERROR, (UINT8) 0, TRUE);
+ }
+
+ } else {
+ if (Packet != NULL) {
+ //
+ // We need to on a non-error, look in the outbound Packet for information and update the NVRAM
+ // location associated with the op-code specified there. This is used on single op-code instances
+ // and not for when a hyperlink sent us a whole page of data.
+ //
+ DataEntry = (EFI_IFR_DATA_ENTRY *) (&Packet->DataArray + 1);
+ if (Packet->DataArray.EntryCount == 1) {
+ switch (DataEntry->OpCode) {
+ case EFI_IFR_STRING_OP:
+ case EFI_IFR_NUMERIC_OP:
+ case EFI_IFR_ORDERED_LIST_OP:
+ case EFI_IFR_ONE_OF_OP:
+ case EFI_IFR_CHECKBOX_OP:
+ CopyMem (
+ &VariableDefinition->NvRamMap[Selection->ThisTag->StorageStart],
+ &DataEntry->Data,
+ Selection->ThisTag->StorageWidth
+ );
+ break;
+
+ case EFI_IFR_NV_ACCESS_COMMAND:
+ CopyMem (
+ &VariableDefinition->NvRamMap[((EFI_IFR_NV_DATA *) Packet)->QuestionId],
+ ((EFI_IFR_NV_DATA *) Packet) + 1,
+ ((EFI_IFR_NV_DATA *) Packet)->StorageWidth
+ );
+ break;
+
+ }
+
+ if (DataEntry->Flags & RESET_REQUIRED) {
+ gResetRequired = TRUE;
+ }
+
+ if (DataEntry->Flags & EXIT_REQUIRED) {
+ gExitRequired = TRUE;
+ }
+
+ if (DataEntry->Flags & SAVE_REQUIRED) {
+ gSaveRequired = TRUE;
+ }
+
+ if (DataEntry->Flags & NV_CHANGED) {
+ gNvUpdateRequired = TRUE;
+ }
+
+ if (DataEntry->Flags & NV_NOT_CHANGED) {
+ gNvUpdateRequired = FALSE;
+ }
+ }
+ }
+ }
+
+ if (Packet != NULL) {
+ gBS->FreePool (Packet);
+ }
+
+ for (BackupIndex = 0; LocalTags->Tags[BackupIndex].Operand != EFI_IFR_END_FORM_OP; BackupIndex++) {
+ switch (LocalTags->Tags[BackupIndex].Operand) {
+ case EFI_IFR_EQ_VAR_VAL_OP:
+ case EFI_IFR_EQ_ID_VAL_OP:
+ case EFI_IFR_EQ_ID_ID_OP:
+ case EFI_IFR_AND_OP:
+ case EFI_IFR_OR_OP:
+ case EFI_IFR_NOT_OP:
+ case EFI_IFR_TRUE_OP:
+ case EFI_IFR_FALSE_OP:
+ case EFI_IFR_GT_OP:
+ case EFI_IFR_GE_OP:
+ case EFI_IFR_EQ_ID_LIST_OP:
+ //
+ // If we encountered a ConsistencyId value, on this page they will be incremental
+ // So register the first value we encounter. We will pass this in when we re-create this page
+ //
+ if ((LocalTags->Tags[BackupIndex].ConsistencyId != 0) && (ConsistencyId == 0)) {
+ ConsistencyId = (UINT16) (LocalTags->Tags[BackupIndex].ConsistencyId - 1);
+ }
+ break;
+ }
+ }
+ //
+ // Delete the buffer associated with previous dynamic page
+ // We will re-allocate a buffer....
+ //
+ gBS->FreePool (LocalTags->Tags);
+
+ Length = 0xF000;
+ Buffer = AllocateZeroPool (Length);
+ ASSERT (Buffer != NULL);
+
+ //
+ // Get the form that was updated by the callback
+ //
+ Hii->GetForms (
+ Hii,
+ Selection->Handle,
+ TargetPage,
+ &Length,
+ Buffer
+ );
+
+ //
+ // Ok, we have the new page.....now we must purge the old page and re-allocate
+ // the tag page with the new data
+ //
+ UpdateNewTagData (
+ Buffer,
+ ConsistencyId,
+ CurrentVariable,
+ LocalTags,
+ FileFormTags
+ );
+
+ //
+ // return the Form Id, Text, and the File's FormTags structure
+ //
+ *FormHandle = LocalTags->Tags[0].Id;
+ *TitleToken = LocalTags->Tags[0].Text;
+ *FormTags = *LocalTags;
+
+ FormTags->Tags[0].CallbackHandle = CallbackHandle;
+ CopyMem (&FormTags->Tags[0].GuidValue, &TagGuid, sizeof (EFI_GUID));
+
+ return ;
+}
+
+UI_MENU_OPTION *
+SetupBrowser (
+ IN UI_MENU_OPTION *Selection,
+ IN BOOLEAN Callback,
+ IN EFI_FILE_FORM_TAGS *FileFormTagsHead,
+ IN UINT8 *CallbackData
+ )
+{
+ UINT16 FormHandle;
+ UINT16 TitleToken;
+ EFI_FORM_TAGS FormTags;
+
+ gEntryNumber = -1;
+ gLastOpr = FALSE;
+ //
+ // Displays the Header and Footer borders
+ //
+ DisplayPageFrame ();
+
+ //
+ // Id of 0 yields the getting of the top form whatever the ID is. Usually the first form in the IFR
+ //
+ ExtractFormHandle (Selection, FileFormTagsHead, 0, &FormHandle, &TitleToken, &FormTags);
+
+ Selection = DisplayForm (Selection, FormHandle, TitleToken, FormTags, FileFormTagsHead, CallbackData);
+
+ //
+ // If selection is null use the former selection
+ //
+ if (Selection == NULL) {
+ return Selection;
+ }
+
+ if (Callback) {
+ return Selection;
+ }
+
+ while (Selection->Tags != NULL) {
+ if (Selection->Previous) {
+ ExtractFormHandle (Selection, FileFormTagsHead, Selection->FormId, &FormHandle, &TitleToken, &FormTags);
+ } else {
+ //
+ // True if a hyperlink/jump is selected
+ //
+ if (Selection->ThisTag->Operand == EFI_IFR_REF_OP && Selection->ThisTag->Id != 0x0000) {
+ if (Selection->ThisTag->Flags & EFI_IFR_FLAG_INTERACTIVE) {
+ ExtractDynamicFormHandle (
+ Selection,
+ CallbackData,
+ FileFormTagsHead,
+ Selection->ThisTag->Id,
+ &FormHandle,
+ &TitleToken,
+ &FormTags
+ );
+ goto DisplayPage;
+ } else {
+ ExtractFormHandle (Selection, FileFormTagsHead, Selection->ThisTag->Id, &FormHandle, &TitleToken, &FormTags);
+ goto DisplayPage;
+ }
+ }
+
+ if ((Selection->ThisTag->Flags & EFI_IFR_FLAG_INTERACTIVE) &&
+ (Selection->ThisTag->Operand != EFI_IFR_PASSWORD_OP)
+ ) {
+ ExtractDynamicFormHandle (
+ Selection,
+ CallbackData,
+ FileFormTagsHead,
+ Selection->FormId,
+ &FormHandle,
+ &TitleToken,
+ &FormTags
+ );
+ } else {
+ ExtractFormHandle (Selection, FileFormTagsHead, Selection->FormId, &FormHandle, &TitleToken, &FormTags);
+ }
+ }
+
+DisplayPage:
+ //
+ // Displays the Header and Footer borders
+ //
+ DisplayPageFrame ();
+
+ Selection = DisplayForm (Selection, FormHandle, TitleToken, FormTags, FileFormTagsHead, CallbackData);
+
+ if (Selection == NULL) {
+ break;
+ }
+ };
+
+ return Selection;
+}