Support call of SendForm() from Callback(), i.e. nested call of SendForm().

git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@9364 6f19259b-4bc3-4df7-8a09-765794883524
This commit is contained in:
xdu2 2009-10-26 03:06:06 +00:00
parent 8b0fc5c1e1
commit ce6d12cce0
4 changed files with 298 additions and 43 deletions

View File

@ -29,6 +29,9 @@ EFI_HII_DATABASE_PROTOCOL *mHiiDatabase;
EFI_HII_STRING_PROTOCOL *mHiiString;
EFI_HII_CONFIG_ROUTING_PROTOCOL *mHiiConfigRouting;
UINTN gBrowserContextCount = 0;
LIST_ENTRY gBrowserContextList = INITIALIZE_LIST_HEAD_VARIABLE (gBrowserContextList);
BANNER_DATA *gBannerData;
EFI_HII_HANDLE gFrontPageHandle;
UINTN gClassOfVfr;
@ -38,8 +41,6 @@ BOOLEAN gNvUpdateRequired;
EFI_HII_HANDLE gHiiHandle;
UINT16 gDirection;
EFI_SCREEN_DESCRIPTOR gScreenDimensions;
BOOLEAN gUpArrow;
BOOLEAN gDownArrow;
//
// Browser Global Strings
@ -85,7 +86,7 @@ EFI_GUID gSetupBrowserGuid = {
0xab368524, 0xb60c, 0x495b, {0xa0, 0x9, 0x12, 0xe8, 0x5b, 0x1a, 0xea, 0x32}
};
FORM_BROWSER_FORMSET *gOldFormSet = NULL;
FORM_BROWSER_FORMSET *gOldFormSet;
FUNCTIION_KEY_SETTING gFunctionKeySettingTable[] = {
//
@ -216,6 +217,11 @@ SendForm (
UINTN Index;
FORM_BROWSER_FORMSET *FormSet;
//
// Save globals used by SendForm()
//
SaveBrowserContext ();
Status = EFI_SUCCESS;
ZeroMem (&gScreenDimensions, sizeof (EFI_SCREEN_DESCRIPTOR));
@ -236,7 +242,8 @@ SendForm (
if ((gScreenDimensions.RightColumn < ScreenDimensions->RightColumn) ||
(gScreenDimensions.BottomRow < ScreenDimensions->BottomRow)
) {
return EFI_INVALID_PARAMETER;
Status = EFI_INVALID_PARAMETER;
goto Done;
} else {
//
// Local dimension validation.
@ -255,7 +262,8 @@ SendForm (
) {
CopyMem (&gScreenDimensions, (VOID *) ScreenDimensions, sizeof (EFI_SCREEN_DESCRIPTOR));
} else {
return EFI_INVALID_PARAMETER;
Status = EFI_INVALID_PARAMETER;
goto Done;
}
}
}
@ -287,6 +295,7 @@ SendForm (
Selection->FormId = FormId;
}
gOldFormSet = NULL;
gNvUpdateRequired = FALSE;
do {
@ -338,6 +347,12 @@ SendForm (
gST->ConOut->SetAttribute (gST->ConOut, EFI_TEXT_ATTR (EFI_LIGHTGRAY, EFI_BLACK));
gST->ConOut->ClearScreen (gST->ConOut);
Done:
//
// Restore globals used by SendForm()
//
RestoreBrowserContext ();
return Status;
}
@ -2511,3 +2526,164 @@ InitializeFormSet (
return Status;
}
/**
Save globals used by previous call to SendForm(). SendForm() may be called from
HiiConfigAccess.Callback(), this will cause SendForm() be reentried.
So, save globals of previous call to SendForm() and restore them upon exit.
**/
VOID
SaveBrowserContext (
VOID
)
{
BROWSER_CONTEXT *Context;
gBrowserContextCount++;
if (gBrowserContextCount == 1) {
//
// This is not reentry of SendForm(), no context to save
//
return;
}
Context = AllocatePool (sizeof (BROWSER_CONTEXT));
ASSERT (Context != NULL);
Context->Signature = BROWSER_CONTEXT_SIGNATURE;
//
// Save FormBrowser context
//
Context->BannerData = gBannerData;
Context->ClassOfVfr = gClassOfVfr;
Context->FunctionKeySetting = gFunctionKeySetting;
Context->ResetRequired = gResetRequired;
Context->NvUpdateRequired = gNvUpdateRequired;
Context->Direction = gDirection;
Context->FunctionNineString = gFunctionNineString;
Context->FunctionTenString = gFunctionTenString;
Context->EnterString = gEnterString;
Context->EnterCommitString = gEnterCommitString;
Context->EnterEscapeString = gEnterEscapeString;
Context->EscapeString = gEscapeString;
Context->SaveFailed = gSaveFailed;
Context->MoveHighlight = gMoveHighlight;
Context->MakeSelection = gMakeSelection;
Context->DecNumericInput = gDecNumericInput;
Context->HexNumericInput = gHexNumericInput;
Context->ToggleCheckBox = gToggleCheckBox;
Context->PromptForData = gPromptForData;
Context->PromptForPassword = gPromptForPassword;
Context->PromptForNewPassword = gPromptForNewPassword;
Context->ConfirmPassword = gConfirmPassword;
Context->ConfirmError = gConfirmError;
Context->PassowordInvalid = gPassowordInvalid;
Context->PressEnter = gPressEnter;
Context->EmptyString = gEmptyString;
Context->AreYouSure = gAreYouSure;
Context->YesResponse = gYesResponse;
Context->NoResponse = gNoResponse;
Context->MiniString = gMiniString;
Context->PlusString = gPlusString;
Context->MinusString = gMinusString;
Context->AdjustNumber = gAdjustNumber;
Context->SaveChanges = gSaveChanges;
Context->OptionMismatch = gOptionMismatch;
Context->PromptBlockWidth = gPromptBlockWidth;
Context->OptionBlockWidth = gOptionBlockWidth;
Context->HelpBlockWidth = gHelpBlockWidth;
Context->OldFormSet = gOldFormSet;
Context->MenuRefreshHead = gMenuRefreshHead;
CopyMem (&Context->ScreenDimensions, &gScreenDimensions, sizeof (gScreenDimensions));
CopyMem (&Context->MenuOption, &gMenuOption, sizeof (gMenuOption));
//
// Insert to FormBrowser context list
//
InsertHeadList (&gBrowserContextList, &Context->Link);
}
/**
Restore globals used by previous call to SendForm().
**/
VOID
RestoreBrowserContext (
VOID
)
{
LIST_ENTRY *Link;
BROWSER_CONTEXT *Context;
ASSERT (gBrowserContextCount != 0);
gBrowserContextCount--;
if (gBrowserContextCount == 0) {
//
// This is not reentry of SendForm(), no context to restore
//
return;
}
ASSERT (!IsListEmpty (&gBrowserContextList));
Link = GetFirstNode (&gBrowserContextList);
Context = BROWSER_CONTEXT_FROM_LINK (Link);
//
// Restore FormBrowser context
//
gBannerData = Context->BannerData;
gClassOfVfr = Context->ClassOfVfr;
gFunctionKeySetting = Context->FunctionKeySetting;
gResetRequired = Context->ResetRequired;
gNvUpdateRequired = Context->NvUpdateRequired;
gDirection = Context->Direction;
gFunctionNineString = Context->FunctionNineString;
gFunctionTenString = Context->FunctionTenString;
gEnterString = Context->EnterString;
gEnterCommitString = Context->EnterCommitString;
gEnterEscapeString = Context->EnterEscapeString;
gEscapeString = Context->EscapeString;
gSaveFailed = Context->SaveFailed;
gMoveHighlight = Context->MoveHighlight;
gMakeSelection = Context->MakeSelection;
gDecNumericInput = Context->DecNumericInput;
gHexNumericInput = Context->HexNumericInput;
gToggleCheckBox = Context->ToggleCheckBox;
gPromptForData = Context->PromptForData;
gPromptForPassword = Context->PromptForPassword;
gPromptForNewPassword = Context->PromptForNewPassword;
gConfirmPassword = Context->ConfirmPassword;
gConfirmError = Context->ConfirmError;
gPassowordInvalid = Context->PassowordInvalid;
gPressEnter = Context->PressEnter;
gEmptyString = Context->EmptyString;
gAreYouSure = Context->AreYouSure;
gYesResponse = Context->YesResponse;
gNoResponse = Context->NoResponse;
gMiniString = Context->MiniString;
gPlusString = Context->PlusString;
gMinusString = Context->MinusString;
gAdjustNumber = Context->AdjustNumber;
gSaveChanges = Context->SaveChanges;
gOptionMismatch = Context->OptionMismatch;
gPromptBlockWidth = Context->PromptBlockWidth;
gOptionBlockWidth = Context->OptionBlockWidth;
gHelpBlockWidth = Context->HelpBlockWidth;
gOldFormSet = Context->OldFormSet;
gMenuRefreshHead = Context->MenuRefreshHead;
CopyMem (&gScreenDimensions, &Context->ScreenDimensions, sizeof (gScreenDimensions));
CopyMem (&gMenuOption, &Context->MenuOption, sizeof (gMenuOption));
//
// Remove from FormBrowser context list
//
RemoveEntryList (&Context->Link);
gBS->FreePool (Context);
}

View File

@ -443,6 +443,64 @@ typedef struct {
LIST_ENTRY FormListHead; // Form list (FORM_BROWSER_FORM)
} FORM_BROWSER_FORMSET;
#define BROWSER_CONTEXT_SIGNATURE SIGNATURE_32 ('B', 'C', 'T', 'X')
typedef struct {
UINTN Signature;
LIST_ENTRY Link;
//
// Globals defined in Setup.c
//
BANNER_DATA *BannerData;
UINTN ClassOfVfr;
UINTN FunctionKeySetting;
BOOLEAN ResetRequired;
BOOLEAN NvUpdateRequired;
UINT16 Direction;
EFI_SCREEN_DESCRIPTOR ScreenDimensions;
CHAR16 *FunctionNineString;
CHAR16 *FunctionTenString;
CHAR16 *EnterString;
CHAR16 *EnterCommitString;
CHAR16 *EnterEscapeString;
CHAR16 *EscapeString;
CHAR16 *SaveFailed;
CHAR16 *MoveHighlight;
CHAR16 *MakeSelection;
CHAR16 *DecNumericInput;
CHAR16 *HexNumericInput;
CHAR16 *ToggleCheckBox;
CHAR16 *PromptForData;
CHAR16 *PromptForPassword;
CHAR16 *PromptForNewPassword;
CHAR16 *ConfirmPassword;
CHAR16 *ConfirmError;
CHAR16 *PassowordInvalid;
CHAR16 *PressEnter;
CHAR16 *EmptyString;
CHAR16 *AreYouSure;
CHAR16 *YesResponse;
CHAR16 *NoResponse;
CHAR16 *MiniString;
CHAR16 *PlusString;
CHAR16 *MinusString;
CHAR16 *AdjustNumber;
CHAR16 *SaveChanges;
CHAR16 *OptionMismatch;
CHAR16 PromptBlockWidth;
CHAR16 OptionBlockWidth;
CHAR16 HelpBlockWidth;
FORM_BROWSER_FORMSET *OldFormSet;
//
// Globals defined in Ui.c
//
LIST_ENTRY MenuOption;
VOID *MenuRefreshHead;
} BROWSER_CONTEXT;
#define BROWSER_CONTEXT_FROM_LINK(a) CR (a, BROWSER_CONTEXT, Link, BROWSER_CONTEXT_SIGNATURE)
extern EFI_HII_DATABASE_PROTOCOL *mHiiDatabase;
extern EFI_HII_STRING_PROTOCOL *mHiiString;
@ -457,8 +515,6 @@ extern BOOLEAN gNvUpdateRequired;
extern EFI_HII_HANDLE gHiiHandle;
extern UINT16 gDirection;
extern EFI_SCREEN_DESCRIPTOR gScreenDimensions;
extern BOOLEAN gUpArrow;
extern BOOLEAN gDownArrow;
extern FORM_BROWSER_FORMSET *gOldFormSet;
@ -976,6 +1032,26 @@ GetIfrBinaryData (
OUT UINT8 **BinaryData
);
/**
Save globals used by previous call to SendForm(). SendForm() may be called from
HiiConfigAccess.Callback(), this will cause SendForm() be reentried.
So, save globals of previous call to SendForm() and restore them upon exit.
**/
VOID
SaveBrowserContext (
VOID
);
/**
Restore globals used by previous call to SendForm().
**/
VOID
RestoreBrowserContext (
VOID
);
/**
This is the routine which an external caller uses to direct the browser
where to obtain it's information.

View File

@ -15,7 +15,7 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
#include "Ui.h"
#include "Setup.h"
LIST_ENTRY Menu;
LIST_ENTRY gMenuOption;
LIST_ENTRY gMenuList = INITIALIZE_LIST_HEAD_VARIABLE (gMenuList);
MENU_REFRESH_ENTRY *gMenuRefreshHead;
@ -145,7 +145,7 @@ UiInitMenu (
VOID
)
{
InitializeListHead (&Menu);
InitializeListHead (&gMenuOption);
}
@ -160,8 +160,8 @@ UiFreeMenu (
{
UI_MENU_OPTION *MenuOption;
while (!IsListEmpty (&Menu)) {
MenuOption = MENU_OPTION_FROM_LINK (Menu.ForwardLink);
while (!IsListEmpty (&gMenuOption)) {
MenuOption = MENU_OPTION_FROM_LINK (gMenuOption.ForwardLink);
RemoveEntryList (&MenuOption->Link);
//
@ -645,7 +645,7 @@ UiAddMenuOption (
MenuOption->ReadOnly = TRUE;
}
InsertTailList (&Menu, &MenuOption->Link);
InsertTailList (&gMenuOption, &MenuOption->Link);
}
return MenuOption;
@ -1353,11 +1353,11 @@ ValueIsScroll (
Temp = Direction ? CurrentPos->BackLink : CurrentPos->ForwardLink;
if (Temp == &Menu) {
if (Temp == &gMenuOption) {
return TRUE;
}
for (; Temp != &Menu; Temp = Direction ? Temp->BackLink : Temp->ForwardLink) {
for (; Temp != &gMenuOption; Temp = Direction ? Temp->BackLink : Temp->ForwardLink) {
MenuOption = MENU_OPTION_FROM_LINK (Temp);
if (IsSelectable (MenuOption)) {
return FALSE;
@ -1399,7 +1399,7 @@ MoveToNextStatement (
if (IsSelectable (NextMenuOption)) {
break;
}
if ((GoUp ? Pos->BackLink : Pos->ForwardLink) == &Menu) {
if ((GoUp ? Pos->BackLink : Pos->ForwardLink) == &gMenuOption) {
HitEnd = TRUE;
break;
}
@ -1420,7 +1420,7 @@ MoveToNextStatement (
if (IsSelectable (NextMenuOption)) {
break;
}
if ((!GoUp ? Pos->BackLink : Pos->ForwardLink) == &Menu) {
if ((!GoUp ? Pos->BackLink : Pos->ForwardLink) == &gMenuOption) {
ASSERT (FALSE);
break;
}
@ -1643,6 +1643,8 @@ UiDisplayMenu (
BOOLEAN NewLine;
BOOLEAN Repaint;
BOOLEAN SavedValue;
BOOLEAN UpArrow;
BOOLEAN DownArrow;
EFI_STATUS Status;
EFI_INPUT_KEY Key;
LIST_ENTRY *Link;
@ -1679,8 +1681,8 @@ UiDisplayMenu (
DefaultId = 0;
OutputString = NULL;
gUpArrow = FALSE;
gDownArrow = FALSE;
UpArrow = FALSE;
DownArrow = FALSE;
SkipValue = 0;
OldSkipValue = 0;
MenuRefreshEntry = gMenuRefreshHead;
@ -1708,7 +1710,7 @@ UiDisplayMenu (
Selection->OptionCol = gPromptBlockWidth + 1 + LocalScreen.LeftColumn;
Selection->Statement = NULL;
TopOfScreen = Menu.ForwardLink;
TopOfScreen = gMenuOption.ForwardLink;
Repaint = TRUE;
MenuOption = NULL;
@ -1734,7 +1736,7 @@ UiDisplayMenu (
//
// Get user's selection
//
NewPos = Menu.ForwardLink;
NewPos = gMenuOption.ForwardLink;
gST->ConOut->EnableCursor (gST->ConOut, FALSE);
UpdateStatusBar (REFRESH_STATUS_BAR, (UINT8) 0, TRUE);
@ -1744,7 +1746,7 @@ UiDisplayMenu (
while (TRUE) {
switch (ControlFlag) {
case CfInitialization:
if (IsListEmpty (&Menu)) {
if (IsListEmpty (&gMenuOption)) {
ControlFlag = CfReadKey;
} else {
ControlFlag = CfCheckSelection;
@ -1766,8 +1768,8 @@ UiDisplayMenu (
//
// Display menu
//
gDownArrow = FALSE;
gUpArrow = FALSE;
DownArrow = FALSE;
UpArrow = FALSE;
Row = TopRow;
Temp = SkipValue;
@ -1784,7 +1786,7 @@ UiDisplayMenu (
UiFreeRefreshList ();
MinRefreshInterval = 0;
for (Link = TopOfScreen; Link != &Menu; Link = Link->ForwardLink) {
for (Link = TopOfScreen; Link != &gMenuOption; Link = Link->ForwardLink) {
MenuOption = MENU_OPTION_FROM_LINK (Link);
MenuOption->Row = Row;
MenuOption->Col = Col;
@ -1989,7 +1991,7 @@ UiDisplayMenu (
if (Row > BottomRow) {
if (!ValueIsScroll (FALSE, Link)) {
gDownArrow = TRUE;
DownArrow = TRUE;
}
Row = BottomRow + 1;
@ -1998,10 +2000,10 @@ UiDisplayMenu (
}
if (!ValueIsScroll (TRUE, TopOfScreen)) {
gUpArrow = TRUE;
UpArrow = TRUE;
}
if (gUpArrow) {
if (UpArrow) {
gST->ConOut->SetAttribute (gST->ConOut, ARROW_TEXT | ARROW_BACKGROUND);
PrintAt (
LocalScreen.LeftColumn + gPromptBlockWidth + gOptionBlockWidth + 1,
@ -2012,7 +2014,7 @@ UiDisplayMenu (
gST->ConOut->SetAttribute (gST->ConOut, FIELD_TEXT | FIELD_BACKGROUND);
}
if (gDownArrow) {
if (DownArrow) {
gST->ConOut->SetAttribute (gST->ConOut, ARROW_TEXT | ARROW_BACKGROUND);
PrintAt (
LocalScreen.LeftColumn + gPromptBlockWidth + gOptionBlockWidth + 1,
@ -2043,10 +2045,10 @@ UiDisplayMenu (
Repaint = FALSE;
if (Selection->QuestionId != 0) {
NewPos = Menu.ForwardLink;
NewPos = gMenuOption.ForwardLink;
SavedMenuOption = MENU_OPTION_FROM_LINK (NewPos);
while (SavedMenuOption->ThisTag->QuestionId != Selection->QuestionId && NewPos->ForwardLink != &Menu) {
while (SavedMenuOption->ThisTag->QuestionId != Selection->QuestionId && NewPos->ForwardLink != &gMenuOption) {
NewPos = NewPos->ForwardLink;
SavedMenuOption = MENU_OPTION_FROM_LINK (NewPos);
}
@ -2439,21 +2441,21 @@ UiDisplayMenu (
// If the screen has no menu items, and the user didn't select UiReset
// ignore the selection and go back to reading keys.
//
if (IsListEmpty (&Menu)) {
if (IsListEmpty (&gMenuOption)) {
ControlFlag = CfReadKey;
break;
}
//
// if there is nothing logical to place a cursor on, just move on to wait for a key.
//
for (Link = Menu.ForwardLink; Link != &Menu; Link = Link->ForwardLink) {
for (Link = gMenuOption.ForwardLink; Link != &gMenuOption; Link = Link->ForwardLink) {
NextMenuOption = MENU_OPTION_FROM_LINK (Link);
if (IsSelectable (NextMenuOption)) {
break;
}
}
if (Link == &Menu) {
if (Link == &gMenuOption) {
ControlFlag = CfPrepareToReadKey;
break;
}
@ -2744,7 +2746,7 @@ UiDisplayMenu (
SavedListEntry = TopOfScreen;
if (NewPos->BackLink != &Menu) {
if (NewPos->BackLink != &gMenuOption) {
NewLine = TRUE;
//
// Adjust Date/Time position before we advance forward.
@ -2754,7 +2756,7 @@ UiDisplayMenu (
//
// Caution that we have already rewind to the top, don't go backward in this situation.
//
if (NewPos->BackLink != &Menu) {
if (NewPos->BackLink != &gMenuOption) {
NewPos = NewPos->BackLink;
}
@ -2799,8 +2801,8 @@ UiDisplayMenu (
// it means that we hit the begining MenuOption that can be focused
// so we simply scroll to the top
//
if (SavedListEntry != Menu.ForwardLink) {
TopOfScreen = Menu.ForwardLink;
if (SavedListEntry != gMenuOption.ForwardLink) {
TopOfScreen = gMenuOption.ForwardLink;
Repaint = TRUE;
}
}
@ -2830,7 +2832,7 @@ UiDisplayMenu (
case CfUiPageUp:
ControlFlag = CfCheckSelection;
if (NewPos->BackLink == &Menu) {
if (NewPos->BackLink == &gMenuOption) {
NewLine = FALSE;
Repaint = FALSE;
break;
@ -2841,7 +2843,7 @@ UiDisplayMenu (
Link = TopOfScreen;
PreviousMenuOption = MENU_OPTION_FROM_LINK (Link);
Index = BottomRow;
while ((Index >= TopRow) && (Link->BackLink != &Menu)) {
while ((Index >= TopRow) && (Link->BackLink != &gMenuOption)) {
Index = Index - PreviousMenuOption->Skip;
Link = Link->BackLink;
PreviousMenuOption = MENU_OPTION_FROM_LINK (Link);
@ -2859,7 +2861,7 @@ UiDisplayMenu (
// This happens when there is no MenuOption can be focused from
// Current MenuOption to the first MenuOption
//
TopOfScreen = Menu.ForwardLink;
TopOfScreen = gMenuOption.ForwardLink;
}
Index += Difference;
if (Index < TopRow) {
@ -2884,7 +2886,7 @@ UiDisplayMenu (
case CfUiPageDown:
ControlFlag = CfCheckSelection;
if (NewPos->ForwardLink == &Menu) {
if (NewPos->ForwardLink == &gMenuOption) {
NewLine = FALSE;
Repaint = FALSE;
break;
@ -2895,7 +2897,7 @@ UiDisplayMenu (
Link = TopOfScreen;
NextMenuOption = MENU_OPTION_FROM_LINK (Link);
Index = TopRow;
while ((Index <= BottomRow) && (Link->ForwardLink != &Menu)) {
while ((Index <= BottomRow) && (Link->ForwardLink != &gMenuOption)) {
Index = Index + NextMenuOption->Skip;
Link = Link->ForwardLink;
NextMenuOption = MENU_OPTION_FROM_LINK (Link);
@ -2940,7 +2942,7 @@ UiDisplayMenu (
SavedListEntry = NewPos;
DistanceValue = AdjustDateAndTimePosition (FALSE, &NewPos);
if (NewPos->ForwardLink != &Menu) {
if (NewPos->ForwardLink != &gMenuOption) {
MenuOption = MENU_OPTION_FROM_LINK (NewPos);
NewLine = TRUE;
NewPos = NewPos->ForwardLink;

View File

@ -190,6 +190,7 @@ typedef struct {
} SCREEN_OPERATION_T0_CONTROL_FLAG;
extern LIST_ENTRY gMenuOption;
extern MENU_REFRESH_ENTRY *gMenuRefreshHead;
extern UI_MENU_SELECTION *gCurrentSelection;
extern BOOLEAN mHiiPackageListUpdated;