]> git.proxmox.com Git - mirror_edk2.git/blobdiff - MdeModulePkg/Universal/SetupBrowserDxe/Setup.c
Enable SetupBrowser to support multiple form class guid.
[mirror_edk2.git] / MdeModulePkg / Universal / SetupBrowserDxe / Setup.c
index ae73f09938bd8b6776cb0d27bdfa552b1e9a3593..da690eb97e6165029b599ebc62a6de1d81798c39 100644 (file)
@@ -13,8 +13,6 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
 **/\r
 \r
 #include "Setup.h"\r
-#include "Ui.h"\r
-\r
 \r
 SETUP_DRIVER_PRIVATE_DATA  mPrivateData = {\r
   SETUP_DRIVER_SIGNATURE,\r
@@ -29,6 +27,9 @@ EFI_HII_DATABASE_PROTOCOL         *mHiiDatabase;
 EFI_HII_STRING_PROTOCOL           *mHiiString;\r
 EFI_HII_CONFIG_ROUTING_PROTOCOL   *mHiiConfigRouting;\r
 \r
+UINTN           gBrowserContextCount = 0;\r
+LIST_ENTRY      gBrowserContextList = INITIALIZE_LIST_HEAD_VARIABLE (gBrowserContextList);\r
+\r
 BANNER_DATA           *gBannerData;\r
 EFI_HII_HANDLE        gFrontPageHandle;\r
 UINTN                 gClassOfVfr;\r
@@ -38,8 +39,6 @@ BOOLEAN               gNvUpdateRequired;
 EFI_HII_HANDLE        gHiiHandle;\r
 UINT16                gDirection;\r
 EFI_SCREEN_DESCRIPTOR gScreenDimensions;\r
-BOOLEAN               gUpArrow;\r
-BOOLEAN               gDownArrow;\r
 \r
 //\r
 // Browser Global Strings\r
@@ -73,6 +72,7 @@ CHAR16            *gMinusString;
 CHAR16            *gAdjustNumber;\r
 CHAR16            *gSaveChanges;\r
 CHAR16            *gOptionMismatch;\r
+CHAR16            *gFormSuppress;\r
 \r
 CHAR16            *mUnknownString = L"!";\r
 \r
@@ -85,7 +85,7 @@ EFI_GUID  gSetupBrowserGuid = {
   0xab368524, 0xb60c, 0x495b, {0xa0, 0x9, 0x12, 0xe8, 0x5b, 0x1a, 0xea, 0x32}\r
 };\r
 \r
-FORM_BROWSER_FORMSET  *gOldFormSet = NULL;\r
+FORM_BROWSER_FORMSET  *gOldFormSet;\r
 \r
 FUNCTIION_KEY_SETTING gFunctionKeySettingTable[] = {\r
   //\r
@@ -216,6 +216,11 @@ SendForm (
   UINTN                         Index;\r
   FORM_BROWSER_FORMSET          *FormSet;\r
 \r
+  //\r
+  // Save globals used by SendForm()\r
+  //\r
+  SaveBrowserContext ();\r
+\r
   Status = EFI_SUCCESS;\r
   ZeroMem (&gScreenDimensions, sizeof (EFI_SCREEN_DESCRIPTOR));\r
 \r
@@ -236,7 +241,8 @@ SendForm (
     if ((gScreenDimensions.RightColumn < ScreenDimensions->RightColumn) ||\r
         (gScreenDimensions.BottomRow < ScreenDimensions->BottomRow)\r
         ) {\r
-      return EFI_INVALID_PARAMETER;\r
+      Status = EFI_INVALID_PARAMETER;\r
+      goto Done;\r
     } else {\r
       //\r
       // Local dimension validation.\r
@@ -255,7 +261,8 @@ SendForm (
         ) {\r
         CopyMem (&gScreenDimensions, (VOID *) ScreenDimensions, sizeof (EFI_SCREEN_DESCRIPTOR));\r
       } else {\r
-        return EFI_INVALID_PARAMETER;\r
+        Status = EFI_INVALID_PARAMETER;\r
+        goto Done;\r
       }\r
     }\r
   }\r
@@ -270,7 +277,6 @@ SendForm (
   InitializeBrowserStrings ();\r
 \r
   gFunctionKeySetting = DEFAULT_FUNCTION_KEY_SETTING;\r
-  gClassOfVfr         = FORMSET_CLASS_PLATFORM_SETUP;\r
 \r
   //\r
   // Ensure we are in Text mode\r
@@ -287,6 +293,7 @@ SendForm (
       Selection->FormId = FormId;\r
     }\r
 \r
+    gOldFormSet = NULL;\r
     gNvUpdateRequired = FALSE;\r
 \r
     do {\r
@@ -338,6 +345,12 @@ SendForm (
   gST->ConOut->SetAttribute (gST->ConOut, EFI_TEXT_ATTR (EFI_LIGHTGRAY, EFI_BLACK));\r
   gST->ConOut->ClearScreen (gST->ConOut);\r
 \r
+Done:\r
+  //\r
+  // Restore globals used by SendForm()\r
+  //\r
+  RestoreBrowserContext ();\r
+\r
   return Status;\r
 }\r
 \r
@@ -928,6 +941,10 @@ ConfigRespToStorage (
     break;\r
 \r
   case EFI_HII_VARSTORE_NAME_VALUE:\r
+    StrPtr = StrStr (ConfigResp, L"PATH");\r
+    if (StrPtr == NULL) {\r
+      break;\r
+    }\r
     StrPtr = StrStr (ConfigResp, L"&");\r
     while (StrPtr != NULL) {\r
       //\r
@@ -1984,10 +2001,12 @@ ExtractFormDefault (
   return EFI_SUCCESS;\r
 }\r
 \r
-\r
 /**\r
   Initialize Question's Edit copy from Storage.\r
 \r
+  @param  Selection              Selection contains the information about \r
+                                 the Selection, form and formset to be displayed.\r
+                                 Selection action may be updated in retrieve callback.\r
   @param  FormSet                FormSet data structure.\r
   @param  Form                   Form data structure.\r
 \r
@@ -1996,14 +2015,19 @@ ExtractFormDefault (
 **/\r
 EFI_STATUS\r
 LoadFormConfig (\r
-  IN FORM_BROWSER_FORMSET             *FormSet,\r
-  IN FORM_BROWSER_FORM                *Form\r
+  IN OUT UI_MENU_SELECTION    *Selection,\r
+  IN FORM_BROWSER_FORMSET     *FormSet,\r
+  IN FORM_BROWSER_FORM        *Form\r
   )\r
 {\r
-  EFI_STATUS              Status;\r
-  LIST_ENTRY              *Link;\r
-  FORM_BROWSER_STATEMENT  *Question;\r
-\r
+  EFI_STATUS                  Status;\r
+  LIST_ENTRY                  *Link;\r
+  FORM_BROWSER_STATEMENT      *Question;\r
+  UINT8                       *BufferValue;\r
+  UINTN                       StorageWidth;\r
+  EFI_HII_VALUE               *HiiValue;\r
+  EFI_BROWSER_ACTION_REQUEST  ActionRequest;\r
+  \r
   Link = GetFirstNode (&Form->StatementListHead);\r
   while (!IsNull (&Form->StatementListHead, Link)) {\r
     Question = FORM_BROWSER_STATEMENT_FROM_LINK (Link);\r
@@ -2015,6 +2039,87 @@ LoadFormConfig (
     if (EFI_ERROR (Status)) {\r
       return Status;\r
     }\r
+    \r
+    //\r
+    // Check whether EfiVarstore with CallBack can be got.\r
+    //\r
+    if ((Question->QuestionId != 0) && (Question->Storage != NULL) &&\r
+        (Question->Storage->Type == EFI_HII_VARSTORE_EFI_VARIABLE) && \r
+        ((Question->QuestionFlags & EFI_IFR_FLAG_CALLBACK) == EFI_IFR_FLAG_CALLBACK)) {\r
+      //\r
+      // ConfigAccess can't be NULL.\r
+      //\r
+      if (FormSet->ConfigAccess == NULL) {\r
+        return EFI_UNSUPPORTED;\r
+      }\r
+      //\r
+      // Check QuestionValue does exist.\r
+      //\r
+      StorageWidth = Question->StorageWidth;\r
+      if (Question->BufferValue != NULL) {\r
+        BufferValue  = Question->BufferValue;\r
+      } else {\r
+        BufferValue = (UINT8 *) &Question->HiiValue.Value;\r
+      }\r
+      Status = gRT->GetVariable (\r
+                       Question->VariableName,\r
+                       &Question->Storage->Guid,\r
+                       NULL,\r
+                       &StorageWidth,\r
+                       BufferValue\r
+                       );\r
+\r
+      if (!EFI_ERROR (Status)) {\r
+        ActionRequest = EFI_BROWSER_ACTION_REQUEST_NONE;\r
+        HiiValue = &Question->HiiValue;\r
+        BufferValue = (UINT8 *) &Question->HiiValue.Value;\r
+        if (HiiValue->Type == EFI_IFR_TYPE_STRING) {\r
+          //\r
+          // Create String in HII database for Configuration Driver to retrieve\r
+          //\r
+          HiiValue->Value.string = NewString ((CHAR16 *) Question->BufferValue, FormSet->HiiHandle);\r
+        } else if (HiiValue->Type == EFI_IFR_TYPE_BUFFER) {\r
+          BufferValue = Question->BufferValue;\r
+        }\r
+\r
+        Status = FormSet->ConfigAccess->Callback (\r
+                                 FormSet->ConfigAccess,\r
+                                 EFI_BROWSER_ACTION_RETRIEVE,\r
+                                 Question->QuestionId,\r
+                                 HiiValue->Type,\r
+                                 (EFI_IFR_TYPE_VALUE *) BufferValue,\r
+                                 &ActionRequest\r
+                                 );\r
+\r
+        if (HiiValue->Type == EFI_IFR_TYPE_STRING) {\r
+          //\r
+          // Clean the String in HII Database\r
+          //\r
+          DeleteString (HiiValue->Value.string, FormSet->HiiHandle);\r
+        }\r
+\r
+        if (!EFI_ERROR (Status)) {\r
+          switch (ActionRequest) {\r
+          case EFI_BROWSER_ACTION_REQUEST_RESET:\r
+            gResetRequired = TRUE;\r
+            break;\r
+\r
+          case EFI_BROWSER_ACTION_REQUEST_SUBMIT:\r
+            //\r
+            // Till now there is no uncommitted data, so ignore this request\r
+            //\r
+            break;\r
+\r
+          case EFI_BROWSER_ACTION_REQUEST_EXIT:\r
+            Selection->Action = UI_ACTION_EXIT;\r
+            break;\r
+\r
+          default:\r
+            break;\r
+          }\r
+        }\r
+      }\r
+    }\r
 \r
     Link = GetNextNode (&Form->StatementListHead, Link);\r
   }\r
@@ -2022,10 +2127,12 @@ LoadFormConfig (
   return EFI_SUCCESS;\r
 }\r
 \r
-\r
 /**\r
   Initialize Question's Edit copy from Storage for the whole Formset.\r
 \r
+  @param  Selection              Selection contains the information about \r
+                                 the Selection, form and formset to be displayed.\r
+                                 Selection action may be updated in retrieve callback.\r
   @param  FormSet                FormSet data structure.\r
 \r
   @retval EFI_SUCCESS            The function completed successfully.\r
@@ -2033,12 +2140,13 @@ LoadFormConfig (
 **/\r
 EFI_STATUS\r
 LoadFormSetConfig (\r
-  IN FORM_BROWSER_FORMSET             *FormSet\r
+  IN OUT UI_MENU_SELECTION    *Selection,\r
+  IN     FORM_BROWSER_FORMSET *FormSet\r
   )\r
 {\r
-  EFI_STATUS          Status;\r
-  LIST_ENTRY          *Link;\r
-  FORM_BROWSER_FORM   *Form;\r
+  EFI_STATUS            Status;\r
+  LIST_ENTRY            *Link;\r
+  FORM_BROWSER_FORM     *Form;\r
 \r
   Link = GetFirstNode (&FormSet->FormListHead);\r
   while (!IsNull (&FormSet->FormListHead, Link)) {\r
@@ -2047,7 +2155,7 @@ LoadFormSetConfig (
     //\r
     // Initialize local copy of Value for each Form\r
     //\r
-    Status = LoadFormConfig (FormSet, Form);\r
+    Status = LoadFormConfig (Selection, FormSet, Form);\r
     if (EFI_ERROR (Status)) {\r
       return Status;\r
     }\r
@@ -2058,7 +2166,6 @@ LoadFormSetConfig (
   return EFI_SUCCESS;\r
 }\r
 \r
-\r
 /**\r
   Fill storage's edit copy with settings requested from Configuration Driver.\r
 \r
@@ -2258,9 +2365,11 @@ InitializeCurrentSetting (
   Fetch the Ifr binary data of a FormSet.\r
 \r
   @param  Handle                 PackageList Handle\r
-  @param  FormSetGuid            GUID of a formset. If not specified (NULL or zero\r
-                                 GUID), take the first FormSet found in package\r
-                                 list.\r
+  @param  FormSetGuid            On input, GUID or class GUID of a formset. If not\r
+                                 specified (NULL or zero GUID), take the first\r
+                                 FormSet with class GUID EFI_HII_PLATFORM_SETUP_FORMSET_GUID\r
+                                 found in package list.\r
+                                 On output, GUID of the formset found(if not NULL).\r
   @param  BinaryLength           The length of the FormSet IFR binary.\r
   @param  BinaryData             The buffer designed to receive the FormSet.\r
 \r
@@ -2286,25 +2395,25 @@ GetIfrBinaryData (
   UINT8                        *OpCodeData;\r
   UINT32                       Offset;\r
   UINT32                       Offset2;\r
-  BOOLEAN                      ReturnDefault;\r
   UINT32                       PackageListLength;\r
   EFI_HII_PACKAGE_HEADER       PackageHeader;\r
   UINT8                        Index;\r
   UINT8                        NumberOfClassGuid;\r
-  BOOLEAN                      IsSetupClassGuid;\r
+  BOOLEAN                      ClassGuidMatch;\r
   EFI_GUID                     *ClassGuid;\r
+  EFI_GUID                     *ComparingGuid;\r
 \r
   OpCodeData = NULL;\r
   Package = NULL;\r
-  ZeroMem (&PackageHeader, sizeof (EFI_HII_PACKAGE_HEADER));;\r
+  ZeroMem (&PackageHeader, sizeof (EFI_HII_PACKAGE_HEADER));\r
 \r
   //\r
-  // if FormSetGuid is NULL or zero GUID, return first FormSet in the package list\r
+  // if FormSetGuid is NULL or zero GUID, return first Setup FormSet in the package list\r
   //\r
   if (FormSetGuid == NULL || CompareGuid (FormSetGuid, &gZeroGuid)) {\r
-    ReturnDefault = TRUE;\r
+    ComparingGuid = &gEfiHiiPlatformSetupFormsetGuid;\r
   } else {\r
-    ReturnDefault = FALSE;\r
+    ComparingGuid = FormSetGuid;\r
   }\r
 \r
   //\r
@@ -2331,6 +2440,7 @@ GetIfrBinaryData (
   Offset2 = 0;\r
   CopyMem (&PackageListLength, &HiiPackageList->PackageLength, sizeof (UINT32));\r
 \r
+  ClassGuidMatch = FALSE;\r
   while (Offset < PackageListLength) {\r
     Package = ((UINT8 *) HiiPackageList) + Offset;\r
     CopyMem (&PackageHeader, Package, sizeof (EFI_HII_PACKAGE_HEADER));\r
@@ -2345,30 +2455,24 @@ GetIfrBinaryData (
 \r
         if (((EFI_IFR_OP_HEADER *) OpCodeData)->OpCode == EFI_IFR_FORM_SET_OP) {\r
           //\r
-          // Check whether return default FormSet\r
+          // Try to compare against formset GUID\r
           //\r
-          if (ReturnDefault) {\r
-            //\r
-            // Check ClassGuid of formset OpCode\r
-            //\r
-            IsSetupClassGuid  = FALSE;\r
-            NumberOfClassGuid = (UINT8) (((EFI_IFR_FORM_SET *) OpCodeData)->Flags & 0x3);\r
-            ClassGuid         = (EFI_GUID *) (OpCodeData + sizeof (EFI_IFR_FORM_SET));\r
-            for (Index = 0; Index < NumberOfClassGuid; Index++) {\r
-              if (CompareGuid (ClassGuid + Index, &gEfiHiiPlatformSetupFormsetGuid)) {\r
-                IsSetupClassGuid = TRUE;\r
-                break;\r
-              }\r
-            }\r
-            if (IsSetupClassGuid) {\r
-              break;\r
-            }\r
+          if (CompareGuid (ComparingGuid, (EFI_GUID *)(OpCodeData + sizeof (EFI_IFR_OP_HEADER)))) {\r
+            break;\r
           }\r
 \r
           //\r
-          // FormSet GUID is specified, check it\r
+          // Try to compare against formset class GUID\r
           //\r
-          if (CompareGuid (FormSetGuid, (EFI_GUID *)(OpCodeData + sizeof (EFI_IFR_OP_HEADER)))) {\r
+          NumberOfClassGuid = (UINT8) (((EFI_IFR_FORM_SET *) OpCodeData)->Flags & 0x3);\r
+          ClassGuid         = (EFI_GUID *) (OpCodeData + sizeof (EFI_IFR_FORM_SET));\r
+          for (Index = 0; Index < NumberOfClassGuid; Index++) {\r
+            if (CompareGuid (ComparingGuid, ClassGuid + Index)) {\r
+              ClassGuidMatch = TRUE;\r
+              break;\r
+            }\r
+          }\r
+          if (ClassGuidMatch) {\r
             break;\r
           }\r
         }\r
@@ -2395,9 +2499,9 @@ GetIfrBinaryData (
     return EFI_NOT_FOUND;\r
   }\r
 \r
-  if (ReturnDefault && FormSetGuid != NULL) {\r
+  if (ClassGuidMatch && (FormSetGuid != NULL)) {\r
     //\r
-    // Return the default FormSet GUID\r
+    // Return the FormSet GUID\r
     //\r
     CopyMem (FormSetGuid, &((EFI_IFR_FORM_SET *) OpCodeData)->Guid, sizeof (EFI_GUID));\r
   }\r
@@ -2424,9 +2528,11 @@ GetIfrBinaryData (
   Initialize the internal data structure of a FormSet.\r
 \r
   @param  Handle                 PackageList Handle\r
-  @param  FormSetGuid            GUID of a formset. If not specified (NULL or zero\r
-                                 GUID), take the first FormSet found in package\r
-                                 list.\r
+  @param  FormSetGuid            On input, GUID or class GUID of a formset. If not\r
+                                 specified (NULL or zero GUID), take the first\r
+                                 FormSet with class GUID EFI_HII_PLATFORM_SETUP_FORMSET_GUID\r
+                                 found in package list.\r
+                                 On output, GUID of the formset found(if not NULL).\r
   @param  FormSet                FormSet data structure.\r
 \r
   @retval EFI_SUCCESS            The function completed successfully.\r
@@ -2481,9 +2587,25 @@ InitializeFormSet (
     return Status;\r
   }\r
 \r
+  //\r
+  // Set VFR type by FormSet SubClass field\r
+  //\r
   gClassOfVfr = FORMSET_CLASS_PLATFORM_SETUP;\r
   if (FormSet->SubClass == EFI_FRONT_PAGE_SUBCLASS) {\r
     gClassOfVfr = FORMSET_CLASS_FRONT_PAGE;\r
+  }\r
+  \r
+  //\r
+  // Set VFR type by FormSet class guid\r
+  //\r
+  for (Index = 0; Index < 3; Index ++) {\r
+    if (CompareGuid (&FormSet->ClassGuid[Index], &gEfiHiiPlatformSetupFormsetGuid)) {\r
+      gClassOfVfr |= FORMSET_CLASS_PLATFORM_SETUP;\r
+      break;\r
+    }\r
+  }\r
+\r
+  if ((gClassOfVfr & FORMSET_CLASS_FRONT_PAGE) == FORMSET_CLASS_FRONT_PAGE) {\r
     gFrontPageHandle = FormSet->HiiHandle;\r
   }\r
 \r
@@ -2511,3 +2633,166 @@ InitializeFormSet (
 \r
   return Status;\r
 }\r
+\r
+\r
+/**\r
+  Save globals used by previous call to SendForm(). SendForm() may be called from \r
+  HiiConfigAccess.Callback(), this will cause SendForm() be reentried.\r
+  So, save globals of previous call to SendForm() and restore them upon exit.\r
+\r
+**/\r
+VOID\r
+SaveBrowserContext (\r
+  VOID\r
+  )\r
+{\r
+  BROWSER_CONTEXT  *Context;\r
+\r
+  gBrowserContextCount++;\r
+  if (gBrowserContextCount == 1) {\r
+    //\r
+    // This is not reentry of SendForm(), no context to save\r
+    //\r
+    return;\r
+  }\r
+\r
+  Context = AllocatePool (sizeof (BROWSER_CONTEXT));\r
+  ASSERT (Context != NULL);\r
+\r
+  Context->Signature = BROWSER_CONTEXT_SIGNATURE;\r
+\r
+  //\r
+  // Save FormBrowser context\r
+  //\r
+  Context->BannerData           = gBannerData;\r
+  Context->ClassOfVfr           = gClassOfVfr;\r
+  Context->FunctionKeySetting   = gFunctionKeySetting;\r
+  Context->ResetRequired        = gResetRequired;\r
+  Context->NvUpdateRequired     = gNvUpdateRequired;\r
+  Context->Direction            = gDirection;\r
+  Context->FunctionNineString   = gFunctionNineString;\r
+  Context->FunctionTenString    = gFunctionTenString;\r
+  Context->EnterString          = gEnterString;\r
+  Context->EnterCommitString    = gEnterCommitString;\r
+  Context->EnterEscapeString    = gEnterEscapeString;\r
+  Context->EscapeString         = gEscapeString;\r
+  Context->SaveFailed           = gSaveFailed;\r
+  Context->MoveHighlight        = gMoveHighlight;\r
+  Context->MakeSelection        = gMakeSelection;\r
+  Context->DecNumericInput      = gDecNumericInput;\r
+  Context->HexNumericInput      = gHexNumericInput;\r
+  Context->ToggleCheckBox       = gToggleCheckBox;\r
+  Context->PromptForData        = gPromptForData;\r
+  Context->PromptForPassword    = gPromptForPassword;\r
+  Context->PromptForNewPassword = gPromptForNewPassword;\r
+  Context->ConfirmPassword      = gConfirmPassword;\r
+  Context->ConfirmError         = gConfirmError;\r
+  Context->PassowordInvalid     = gPassowordInvalid;\r
+  Context->PressEnter           = gPressEnter;\r
+  Context->EmptyString          = gEmptyString;\r
+  Context->AreYouSure           = gAreYouSure;\r
+  Context->YesResponse          = gYesResponse;\r
+  Context->NoResponse           = gNoResponse;\r
+  Context->MiniString           = gMiniString;\r
+  Context->PlusString           = gPlusString;\r
+  Context->MinusString          = gMinusString;\r
+  Context->AdjustNumber         = gAdjustNumber;\r
+  Context->SaveChanges          = gSaveChanges;\r
+  Context->OptionMismatch       = gOptionMismatch;\r
+  Context->FormSuppress         = gFormSuppress;\r
+  Context->PromptBlockWidth     = gPromptBlockWidth;\r
+  Context->OptionBlockWidth     = gOptionBlockWidth;\r
+  Context->HelpBlockWidth       = gHelpBlockWidth;\r
+  Context->OldFormSet           = gOldFormSet;\r
+  Context->MenuRefreshHead      = gMenuRefreshHead;\r
+\r
+  CopyMem (&Context->ScreenDimensions, &gScreenDimensions, sizeof (gScreenDimensions));\r
+  CopyMem (&Context->MenuOption, &gMenuOption, sizeof (gMenuOption));\r
+\r
+  //\r
+  // Insert to FormBrowser context list\r
+  //\r
+  InsertHeadList (&gBrowserContextList, &Context->Link);\r
+}\r
+\r
+\r
+/**\r
+  Restore globals used by previous call to SendForm().\r
+\r
+**/\r
+VOID\r
+RestoreBrowserContext (\r
+  VOID\r
+  )\r
+{\r
+  LIST_ENTRY       *Link;\r
+  BROWSER_CONTEXT  *Context;\r
+\r
+  ASSERT (gBrowserContextCount != 0);\r
+  gBrowserContextCount--;\r
+  if (gBrowserContextCount == 0) {\r
+    //\r
+    // This is not reentry of SendForm(), no context to restore\r
+    //\r
+    return;\r
+  }\r
+\r
+  ASSERT (!IsListEmpty (&gBrowserContextList));\r
+\r
+  Link = GetFirstNode (&gBrowserContextList);\r
+  Context = BROWSER_CONTEXT_FROM_LINK (Link);\r
+\r
+  //\r
+  // Restore FormBrowser context\r
+  //\r
+  gBannerData           = Context->BannerData;\r
+  gClassOfVfr           = Context->ClassOfVfr;\r
+  gFunctionKeySetting   = Context->FunctionKeySetting;\r
+  gResetRequired        = Context->ResetRequired;\r
+  gNvUpdateRequired     = Context->NvUpdateRequired;\r
+  gDirection            = Context->Direction;\r
+  gFunctionNineString   = Context->FunctionNineString;\r
+  gFunctionTenString    = Context->FunctionTenString;\r
+  gEnterString          = Context->EnterString;\r
+  gEnterCommitString    = Context->EnterCommitString;\r
+  gEnterEscapeString    = Context->EnterEscapeString;\r
+  gEscapeString         = Context->EscapeString;\r
+  gSaveFailed           = Context->SaveFailed;\r
+  gMoveHighlight        = Context->MoveHighlight;\r
+  gMakeSelection        = Context->MakeSelection;\r
+  gDecNumericInput      = Context->DecNumericInput;\r
+  gHexNumericInput      = Context->HexNumericInput;\r
+  gToggleCheckBox       = Context->ToggleCheckBox;\r
+  gPromptForData        = Context->PromptForData;\r
+  gPromptForPassword    = Context->PromptForPassword;\r
+  gPromptForNewPassword = Context->PromptForNewPassword;\r
+  gConfirmPassword      = Context->ConfirmPassword;\r
+  gConfirmError         = Context->ConfirmError;\r
+  gPassowordInvalid     = Context->PassowordInvalid;\r
+  gPressEnter           = Context->PressEnter;\r
+  gEmptyString          = Context->EmptyString;\r
+  gAreYouSure           = Context->AreYouSure;\r
+  gYesResponse          = Context->YesResponse;\r
+  gNoResponse           = Context->NoResponse;\r
+  gMiniString           = Context->MiniString;\r
+  gPlusString           = Context->PlusString;\r
+  gMinusString          = Context->MinusString;\r
+  gAdjustNumber         = Context->AdjustNumber;\r
+  gSaveChanges          = Context->SaveChanges;\r
+  gOptionMismatch       = Context->OptionMismatch;\r
+  gFormSuppress         = Context->FormSuppress;\r
+  gPromptBlockWidth     = Context->PromptBlockWidth;\r
+  gOptionBlockWidth     = Context->OptionBlockWidth;\r
+  gHelpBlockWidth       = Context->HelpBlockWidth;\r
+  gOldFormSet           = Context->OldFormSet;\r
+  gMenuRefreshHead      = Context->MenuRefreshHead;\r
+\r
+  CopyMem (&gScreenDimensions, &Context->ScreenDimensions, sizeof (gScreenDimensions));\r
+  CopyMem (&gMenuOption, &Context->MenuOption, sizeof (gMenuOption));\r
+\r
+  //\r
+  // Remove from FormBrowser context list\r
+  //\r
+  RemoveEntryList (&Context->Link);\r
+  gBS->FreePool (Context);\r
+}\r