| /*++ | |
| Copyright (c) 2006 - 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. | |
| 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); | |
| 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; | |
| } | |
| 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); | |
| } | |
| } | |
| 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 | | |
| +------------------------------------------------------------------------------+ | |
| */ | |
| STATIC | |
| 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. | |
| // | |
| 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++; | |
| } | |
| 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 (SecCol, 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 (StartColumnOfHelp, BottomRowOfHelp, 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; | |
| } | |
| } | |
| STATIC | |
| 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 ; | |
| } | |
| STATIC | |
| 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; | |
| } | |
| STATIC | |
| 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)) { | |
| 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) { | |
| 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.... | |
| // | |
| 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; | |
| } |