/*++ | |
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; | |
} |