Home | History | Annotate | Download | only in BootMaint
      1 /** @file
      2   The functions for Boot Maintainence Main menu.
      3 
      4 Copyright (c) 2004 - 2015, Intel Corporation. All rights reserved.<BR>
      5 This program and the accompanying materials
      6 are licensed and made available under the terms and conditions of the BSD License
      7 which accompanies this distribution.  The full text of the license may be found at
      8 http://opensource.org/licenses/bsd-license.php
      9 
     10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
     11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
     12 
     13 **/
     14 
     15 #include "BootMaint.h"
     16 #include "FormGuid.h"
     17 #include "Bds.h"
     18 #include "FrontPage.h"
     19 
     20 EFI_DEVICE_PATH_PROTOCOL  EndDevicePath[] = {
     21   {
     22     END_DEVICE_PATH_TYPE,
     23     END_ENTIRE_DEVICE_PATH_SUBTYPE,
     24     {
     25       END_DEVICE_PATH_LENGTH,
     26       0
     27     }
     28   }
     29 };
     30 
     31 HII_VENDOR_DEVICE_PATH  mBmmHiiVendorDevicePath = {
     32   {
     33     {
     34       HARDWARE_DEVICE_PATH,
     35       HW_VENDOR_DP,
     36       {
     37         (UINT8) (sizeof (VENDOR_DEVICE_PATH)),
     38         (UINT8) ((sizeof (VENDOR_DEVICE_PATH)) >> 8)
     39       }
     40     },
     41     BOOT_MAINT_FORMSET_GUID
     42   },
     43   {
     44     END_DEVICE_PATH_TYPE,
     45     END_ENTIRE_DEVICE_PATH_SUBTYPE,
     46     {
     47       (UINT8) (END_DEVICE_PATH_LENGTH),
     48       (UINT8) ((END_DEVICE_PATH_LENGTH) >> 8)
     49     }
     50   }
     51 };
     52 
     53 HII_VENDOR_DEVICE_PATH  mFeHiiVendorDevicePath = {
     54   {
     55     {
     56       HARDWARE_DEVICE_PATH,
     57       HW_VENDOR_DP,
     58       {
     59         (UINT8) (sizeof (VENDOR_DEVICE_PATH)),
     60         (UINT8) ((sizeof (VENDOR_DEVICE_PATH)) >> 8)
     61       }
     62     },
     63     FILE_EXPLORE_FORMSET_GUID
     64   },
     65   {
     66     END_DEVICE_PATH_TYPE,
     67     END_ENTIRE_DEVICE_PATH_SUBTYPE,
     68     {
     69       (UINT8) (END_DEVICE_PATH_LENGTH),
     70       (UINT8) ((END_DEVICE_PATH_LENGTH) >> 8)
     71     }
     72   }
     73 };
     74 
     75 CHAR16  mBootMaintStorageName[]     = L"BmmData";
     76 CHAR16  mFileExplorerStorageName[]  = L"FeData";
     77 BMM_CALLBACK_DATA *mBmmCallbackInfo = NULL;
     78 
     79 /**
     80   Init all memu.
     81 
     82   @param CallbackData    The BMM context data.
     83 
     84 **/
     85 VOID
     86 InitAllMenu (
     87   IN  BMM_CALLBACK_DATA    *CallbackData
     88   );
     89 
     90 /**
     91   Free up all Menu Option list.
     92 
     93 **/
     94 VOID
     95 FreeAllMenu (
     96   VOID
     97   );
     98 
     99 /**
    100   Initialize all of BMM configuration data in BmmFakeNvData and BmmOldFakeNVData member
    101   in BMM context data and create all of dynamic OP code for BMM.
    102 
    103   @param CallbackData    The BMM context data.
    104 
    105 **/
    106 VOID
    107 InitializeBmmConfig (
    108   IN  BMM_CALLBACK_DATA    *CallbackData
    109   )
    110 {
    111   BM_MENU_ENTRY   *NewMenuEntry;
    112   BM_LOAD_CONTEXT *NewLoadContext;
    113   UINT16          Index;
    114 
    115   ASSERT (CallbackData != NULL);
    116 
    117   //
    118   // Initialize data which located in BMM main page
    119   //
    120   CallbackData->BmmFakeNvData.BootNext = (UINT16) (BootOptionMenu.MenuNumber);
    121   for (Index = 0; Index < BootOptionMenu.MenuNumber; Index++) {
    122     NewMenuEntry    = BOpt_GetMenuEntry (&BootOptionMenu, Index);
    123     NewLoadContext  = (BM_LOAD_CONTEXT *) NewMenuEntry->VariableContext;
    124 
    125     if (NewLoadContext->IsBootNext) {
    126       CallbackData->BmmFakeNvData.BootNext = Index;
    127       break;
    128     }
    129   }
    130 
    131   CallbackData->BmmFakeNvData.BootTimeOut = PcdGet16 (PcdPlatformBootTimeOut);
    132 
    133   //
    134   // Initialize data which located in Boot Options Menu
    135   //
    136   GetBootOrder (CallbackData);
    137   GetLegacyDeviceOrder (CallbackData);
    138 
    139   //
    140   // Initialize data which located in Driver Options Menu
    141   //
    142   GetDriverOrder (CallbackData);
    143 
    144   //
    145   // Initialize data which located in Console Options Menu
    146   //
    147   GetConsoleOutMode (CallbackData);
    148   GetConsoleInCheck (CallbackData);
    149   GetConsoleOutCheck (CallbackData);
    150   GetConsoleErrCheck (CallbackData);
    151   GetTerminalAttribute (CallbackData);
    152 
    153   //
    154   // Backup Initialize BMM configuartion data to BmmOldFakeNVData
    155   //
    156   CopyMem (&CallbackData->BmmOldFakeNVData, &CallbackData->BmmFakeNvData, sizeof (BMM_FAKE_NV_DATA));
    157 }
    158 
    159 /**
    160   Create string tokens for a menu from its help strings and display strings
    161 
    162   @param CallbackData       The BMM context data.
    163   @param HiiHandle          Hii Handle of the package to be updated.
    164   @param MenuOption         The Menu whose string tokens need to be created
    165 
    166   @retval  EFI_SUCCESS      String tokens created successfully
    167   @retval  others           contain some errors
    168 **/
    169 EFI_STATUS
    170 CreateMenuStringToken (
    171   IN BMM_CALLBACK_DATA                *CallbackData,
    172   IN EFI_HII_HANDLE                   HiiHandle,
    173   IN BM_MENU_OPTION                   *MenuOption
    174   )
    175 {
    176   BM_MENU_ENTRY *NewMenuEntry;
    177   UINTN         Index;
    178 
    179   for (Index = 0; Index < MenuOption->MenuNumber; Index++) {
    180     NewMenuEntry = BOpt_GetMenuEntry (MenuOption, Index);
    181 
    182     NewMenuEntry->DisplayStringToken = HiiSetString (
    183                                          HiiHandle,
    184                                          0,
    185                                          NewMenuEntry->DisplayString,
    186                                          NULL
    187                                          );
    188 
    189     if (NULL == NewMenuEntry->HelpString) {
    190       NewMenuEntry->HelpStringToken = NewMenuEntry->DisplayStringToken;
    191     } else {
    192       NewMenuEntry->HelpStringToken = HiiSetString (
    193                                         HiiHandle,
    194                                         0,
    195                                         NewMenuEntry->HelpString,
    196                                         NULL
    197                                         );
    198     }
    199   }
    200 
    201   return EFI_SUCCESS;
    202 }
    203 
    204 /**
    205   This function allows a caller to extract the current configuration for one
    206   or more named elements from the target driver.
    207 
    208 
    209   @param This            Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
    210   @param Request         A null-terminated Unicode string in <ConfigRequest> format.
    211   @param Progress        On return, points to a character in the Request string.
    212                          Points to the string's null terminator if request was successful.
    213                          Points to the most recent '&' before the first failing name/value
    214                          pair (or the beginning of the string if the failure is in the
    215                          first name/value pair) if the request was not successful.
    216   @param Results         A null-terminated Unicode string in <ConfigAltResp> format which
    217                          has all values filled in for the names in the Request string.
    218                          String to be allocated by the called function.
    219 
    220   @retval  EFI_SUCCESS            The Results is filled with the requested values.
    221   @retval  EFI_OUT_OF_RESOURCES   Not enough memory to store the results.
    222   @retval  EFI_INVALID_PARAMETER  Request is NULL, illegal syntax, or unknown name.
    223   @retval  EFI_NOT_FOUND          Routing data doesn't match any storage in this driver.
    224 
    225 **/
    226 EFI_STATUS
    227 EFIAPI
    228 BootMaintExtractConfig (
    229   IN  CONST EFI_HII_CONFIG_ACCESS_PROTOCOL   *This,
    230   IN  CONST EFI_STRING                       Request,
    231   OUT EFI_STRING                             *Progress,
    232   OUT EFI_STRING                             *Results
    233   )
    234 {
    235   EFI_STATUS         Status;
    236   UINTN              BufferSize;
    237   BMM_CALLBACK_DATA  *Private;
    238   EFI_STRING                       ConfigRequestHdr;
    239   EFI_STRING                       ConfigRequest;
    240   BOOLEAN                          AllocatedRequest;
    241   UINTN                            Size;
    242 
    243   if (Progress == NULL || Results == NULL) {
    244     return EFI_INVALID_PARAMETER;
    245   }
    246 
    247   *Progress = Request;
    248   if ((Request != NULL) && !HiiIsConfigHdrMatch (Request, &gBootMaintFormSetGuid, mBootMaintStorageName)) {
    249     return EFI_NOT_FOUND;
    250   }
    251 
    252   ConfigRequestHdr = NULL;
    253   ConfigRequest    = NULL;
    254   AllocatedRequest = FALSE;
    255   Size             = 0;
    256 
    257   Private = BMM_CALLBACK_DATA_FROM_THIS (This);
    258   //
    259   // Convert buffer data to <ConfigResp> by helper function BlockToConfig()
    260   //
    261   BufferSize = sizeof (BMM_FAKE_NV_DATA);
    262   ConfigRequest = Request;
    263   if ((Request == NULL) || (StrStr (Request, L"OFFSET") == NULL)) {
    264     //
    265     // Request has no request element, construct full request string.
    266     // Allocate and fill a buffer large enough to hold the <ConfigHdr> template
    267     // followed by "&OFFSET=0&WIDTH=WWWWWWWWWWWWWWWW" followed by a Null-terminator
    268     //
    269     ConfigRequestHdr = HiiConstructConfigHdr (&gBootMaintFormSetGuid, mBootMaintStorageName, Private->BmmDriverHandle);
    270     Size = (StrLen (ConfigRequestHdr) + 32 + 1) * sizeof (CHAR16);
    271     ConfigRequest = AllocateZeroPool (Size);
    272     ASSERT (ConfigRequest != NULL);
    273     AllocatedRequest = TRUE;
    274     UnicodeSPrint (ConfigRequest, Size, L"%s&OFFSET=0&WIDTH=%016LX", ConfigRequestHdr, (UINT64)BufferSize);
    275     FreePool (ConfigRequestHdr);
    276   }
    277 
    278   Status = gHiiConfigRouting->BlockToConfig (
    279                                 gHiiConfigRouting,
    280                                 ConfigRequest,
    281                                 (UINT8 *) &Private->BmmFakeNvData,
    282                                 BufferSize,
    283                                 Results,
    284                                 Progress
    285                                 );
    286   //
    287   // Free the allocated config request string.
    288   //
    289   if (AllocatedRequest) {
    290     FreePool (ConfigRequest);
    291     ConfigRequest = NULL;
    292   }
    293   //
    294   // Set Progress string to the original request string.
    295   //
    296   if (Request == NULL) {
    297     *Progress = NULL;
    298   } else if (StrStr (Request, L"OFFSET") == NULL) {
    299     *Progress = Request + StrLen (Request);
    300   }
    301 
    302   return Status;
    303 }
    304 
    305 /**
    306   This function applies changes in a driver's configuration.
    307   Input is a Configuration, which has the routing data for this
    308   driver followed by name / value configuration pairs. The driver
    309   must apply those pairs to its configurable storage. If the
    310   driver's configuration is stored in a linear block of data
    311   and the driver's name / value pairs are in <BlockConfig>
    312   format, it may use the ConfigToBlock helper function (above) to
    313   simplify the job. Currently not implemented.
    314 
    315   @param[in]  This                Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
    316   @param[in]  Configuration       A null-terminated Unicode string in
    317                                   <ConfigString> format.
    318   @param[out] Progress            A pointer to a string filled in with the
    319                                   offset of the most recent '&' before the
    320                                   first failing name / value pair (or the
    321                                   beginn ing of the string if the failure
    322                                   is in the first name / value pair) or
    323                                   the terminating NULL if all was
    324                                   successful.
    325 
    326   @retval EFI_SUCCESS             The results have been distributed or are
    327                                   awaiting distribution.
    328   @retval EFI_OUT_OF_RESOURCES    Not enough memory to store the
    329                                   parts of the results that must be
    330                                   stored awaiting possible future
    331                                   protocols.
    332   @retval EFI_INVALID_PARAMETERS  Passing in a NULL for the
    333                                   Results parameter would result
    334                                   in this type of error.
    335   @retval EFI_NOT_FOUND           Target for the specified routing data
    336                                   was not found.
    337 **/
    338 EFI_STATUS
    339 EFIAPI
    340 BootMaintRouteConfig (
    341   IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This,
    342   IN CONST EFI_STRING                     Configuration,
    343   OUT EFI_STRING                          *Progress
    344   )
    345 {
    346   EFI_STATUS                      Status;
    347   UINTN                           BufferSize;
    348   EFI_HII_CONFIG_ROUTING_PROTOCOL *ConfigRouting;
    349   BMM_FAKE_NV_DATA                *NewBmmData;
    350   BMM_FAKE_NV_DATA                *OldBmmData;
    351   BM_CONSOLE_CONTEXT              *NewConsoleContext;
    352   BM_TERMINAL_CONTEXT             *NewTerminalContext;
    353   BM_MENU_ENTRY                   *NewMenuEntry;
    354   BM_LOAD_CONTEXT                 *NewLoadContext;
    355   UINT16                          Index;
    356   BOOLEAN                         TerminalAttChange;
    357   BMM_CALLBACK_DATA               *Private;
    358 
    359   if (Progress == NULL) {
    360     return EFI_INVALID_PARAMETER;
    361   }
    362   *Progress = Configuration;
    363 
    364   if (Configuration == NULL) {
    365     return EFI_INVALID_PARAMETER;
    366   }
    367 
    368   //
    369   // Check routing data in <ConfigHdr>.
    370   // Note: there is no name for Name/Value storage, only GUID will be checked
    371   //
    372   if (!HiiIsConfigHdrMatch (Configuration, &gBootMaintFormSetGuid, mBootMaintStorageName)) {
    373     return EFI_NOT_FOUND;
    374   }
    375 
    376   Status = gBS->LocateProtocol (
    377                   &gEfiHiiConfigRoutingProtocolGuid,
    378                   NULL,
    379                   (VOID**) &ConfigRouting
    380                   );
    381   if (EFI_ERROR (Status)) {
    382     return Status;
    383   }
    384 
    385   Private = BMM_CALLBACK_DATA_FROM_THIS (This);
    386   //
    387   // Get Buffer Storage data from EFI variable
    388   //
    389   BufferSize = sizeof (BMM_FAKE_NV_DATA);
    390   OldBmmData = &Private->BmmOldFakeNVData;
    391   NewBmmData = &Private->BmmFakeNvData;
    392   //
    393   // Convert <ConfigResp> to buffer data by helper function ConfigToBlock()
    394   //
    395   Status = ConfigRouting->ConfigToBlock (
    396                             ConfigRouting,
    397                             Configuration,
    398                             (UINT8 *) NewBmmData,
    399                             &BufferSize,
    400                             Progress
    401                             );
    402   ASSERT_EFI_ERROR (Status);
    403   //
    404   // Compare new and old BMM configuration data and only do action for modified item to
    405   // avoid setting unnecessary non-volatile variable
    406   //
    407 
    408   //
    409   // Check data which located in BMM main page and save the settings if need
    410   //
    411   if (CompareMem (NewBmmData->LegacyFD, OldBmmData->LegacyFD, sizeof (NewBmmData->LegacyFD)) != 0) {
    412     Var_UpdateBBSOption (Private, FORM_SET_FD_ORDER_ID);
    413   }
    414 
    415   if (CompareMem (NewBmmData->LegacyHD, OldBmmData->LegacyHD, sizeof (NewBmmData->LegacyHD)) != 0) {
    416     Var_UpdateBBSOption (Private, FORM_SET_HD_ORDER_ID);
    417   }
    418 
    419   if (CompareMem (NewBmmData->LegacyCD, OldBmmData->LegacyCD, sizeof (NewBmmData->LegacyCD)) != 0) {
    420     Var_UpdateBBSOption (Private, FORM_SET_CD_ORDER_ID);
    421   }
    422 
    423   if (CompareMem (NewBmmData->LegacyNET, OldBmmData->LegacyNET, sizeof (NewBmmData->LegacyNET)) != 0) {
    424     Var_UpdateBBSOption (Private, FORM_SET_NET_ORDER_ID);
    425   }
    426 
    427   if (CompareMem (NewBmmData->LegacyBEV, OldBmmData->LegacyBEV, sizeof (NewBmmData->LegacyBEV)) != 0) {
    428     Var_UpdateBBSOption (Private, FORM_SET_BEV_ORDER_ID);
    429   }
    430 
    431   //
    432   // Change for "delete boot option" page need update NewBmmData->BootOptionOrder, so process
    433   // NewBmmData->BootOptionOrder before NewBmmData->BootOptionDel
    434   //
    435   if (CompareMem (NewBmmData->BootOptionOrder, OldBmmData->BootOptionOrder, sizeof (NewBmmData->BootOptionOrder)) != 0) {
    436     Status = Var_UpdateBootOrder (Private);
    437   }
    438 
    439   //
    440   // Change for "delete driver option" page need update NewBmmData->DriverOptionOrder, so process
    441   // NewBmmData->DriverOptionOrder before NewBmmData->DriverOptionDel
    442   //
    443   if (CompareMem (NewBmmData->DriverOptionOrder, OldBmmData->DriverOptionOrder, sizeof (NewBmmData->DriverOptionOrder)) != 0) {
    444     Status = Var_UpdateDriverOrder (Private);
    445   }
    446 
    447   //
    448   // Check data which located in Boot Options Menu and save the settings if need
    449   //
    450   if (CompareMem (NewBmmData->BootOptionDel, OldBmmData->BootOptionDel, sizeof (NewBmmData->BootOptionDel)) != 0) {
    451     for (Index = 0;
    452          ((Index < BootOptionMenu.MenuNumber) && (Index < (sizeof (NewBmmData->BootOptionDel) / sizeof (NewBmmData->BootOptionDel[0]))));
    453          Index ++) {
    454       NewMenuEntry            = BOpt_GetMenuEntry (&BootOptionMenu, Index);
    455       NewLoadContext          = (BM_LOAD_CONTEXT *) NewMenuEntry->VariableContext;
    456       NewLoadContext->Deleted = NewBmmData->BootOptionDel[Index];
    457       NewBmmData->BootOptionDel[Index] = FALSE;
    458       NewBmmData->BootOptionDelMark[Index] = FALSE;
    459     }
    460 
    461     Var_DelBootOption ();
    462   }
    463 
    464   //
    465   // Check data which located in Driver Options Menu and save the settings if need
    466   //
    467   if (CompareMem (NewBmmData->DriverOptionDel, OldBmmData->DriverOptionDel, sizeof (NewBmmData->DriverOptionDel)) != 0) {
    468     for (Index = 0;
    469          ((Index < DriverOptionMenu.MenuNumber) && (Index < (sizeof (NewBmmData->DriverOptionDel) / sizeof (NewBmmData->DriverOptionDel[0]))));
    470          Index++) {
    471       NewMenuEntry            = BOpt_GetMenuEntry (&DriverOptionMenu, Index);
    472       NewLoadContext          = (BM_LOAD_CONTEXT *) NewMenuEntry->VariableContext;
    473       NewLoadContext->Deleted = NewBmmData->DriverOptionDel[Index];
    474       NewBmmData->DriverOptionDel[Index] = FALSE;
    475       NewBmmData->DriverOptionDelMark[Index] = FALSE;
    476     }
    477     Var_DelDriverOption ();
    478   }
    479 
    480   if (CompareMem (&NewBmmData->BootTimeOut, &OldBmmData->BootTimeOut, sizeof (NewBmmData->BootTimeOut)) != 0) {
    481     Status = gRT->SetVariable (
    482                     L"Timeout",
    483                     &gEfiGlobalVariableGuid,
    484                     EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE,
    485                     sizeof (UINT16),
    486                     &(NewBmmData->BootTimeOut)
    487                     );
    488     ASSERT_EFI_ERROR(Status);
    489 
    490     //
    491     // Bugbug: code not exit in UiApp but in IntelFrameworkModulePkg, need do more check.
    492     //
    493     Private->BmmOldFakeNVData.BootTimeOut = NewBmmData->BootTimeOut;
    494   }
    495 
    496   if (CompareMem (&NewBmmData->BootNext, &OldBmmData->BootNext, sizeof (NewBmmData->BootNext)) != 0) {
    497     Status = Var_UpdateBootNext (Private);
    498   }
    499 
    500   if (CompareMem (&NewBmmData->ConsoleOutMode, &OldBmmData->ConsoleOutMode, sizeof (NewBmmData->ConsoleOutMode)) != 0) {
    501     Var_UpdateConMode (Private);
    502   }
    503 
    504   TerminalAttChange = FALSE;
    505   for (Index = 0; Index < TerminalMenu.MenuNumber; Index++) {
    506 
    507     //
    508     // only need update modified items
    509     //
    510     if (CompareMem (&NewBmmData->COMBaudRate[Index], &OldBmmData->COMBaudRate[Index], sizeof (NewBmmData->COMBaudRate[Index])) == 0 &&
    511          CompareMem (&NewBmmData->COMDataRate[Index], &OldBmmData->COMDataRate[Index], sizeof (NewBmmData->COMDataRate[Index])) == 0 &&
    512          CompareMem (&NewBmmData->COMStopBits[Index], &OldBmmData->COMStopBits[Index], sizeof (NewBmmData->COMStopBits[Index])) == 0 &&
    513          CompareMem (&NewBmmData->COMParity[Index], &OldBmmData->COMParity[Index], sizeof (NewBmmData->COMParity[Index])) == 0 &&
    514          CompareMem (&NewBmmData->COMTerminalType[Index], &OldBmmData->COMTerminalType[Index], sizeof (NewBmmData->COMTerminalType[Index])) == 0 &&
    515          CompareMem (&NewBmmData->COMFlowControl[Index], &OldBmmData->COMFlowControl[Index], sizeof (NewBmmData->COMFlowControl[Index])) == 0) {
    516       continue;
    517     }
    518 
    519     NewMenuEntry = BOpt_GetMenuEntry (&TerminalMenu, Index);
    520     ASSERT (NewMenuEntry != NULL);
    521     NewTerminalContext = (BM_TERMINAL_CONTEXT *) NewMenuEntry->VariableContext;
    522     NewTerminalContext->BaudRateIndex = NewBmmData->COMBaudRate[Index];
    523     ASSERT (NewBmmData->COMBaudRate[Index] < (ARRAY_SIZE (BaudRateList)));
    524     NewTerminalContext->BaudRate      = BaudRateList[NewBmmData->COMBaudRate[Index]].Value;
    525     NewTerminalContext->DataBitsIndex = NewBmmData->COMDataRate[Index];
    526     ASSERT (NewBmmData->COMDataRate[Index] < (ARRAY_SIZE (DataBitsList)));
    527     NewTerminalContext->DataBits      = (UINT8) DataBitsList[NewBmmData->COMDataRate[Index]].Value;
    528     NewTerminalContext->StopBitsIndex = NewBmmData->COMStopBits[Index];
    529     ASSERT (NewBmmData->COMStopBits[Index] < (ARRAY_SIZE (StopBitsList)));
    530     NewTerminalContext->StopBits      = (UINT8) StopBitsList[NewBmmData->COMStopBits[Index]].Value;
    531     NewTerminalContext->ParityIndex   = NewBmmData->COMParity[Index];
    532     ASSERT (NewBmmData->COMParity[Index] < (ARRAY_SIZE (ParityList)));
    533     NewTerminalContext->Parity        = (UINT8) ParityList[NewBmmData->COMParity[Index]].Value;
    534     NewTerminalContext->TerminalType  = NewBmmData->COMTerminalType[Index];
    535     NewTerminalContext->FlowControl   = NewBmmData->COMFlowControl[Index];
    536     ChangeTerminalDevicePath (
    537       &(NewTerminalContext->DevicePath),
    538       FALSE
    539       );
    540     TerminalAttChange = TRUE;
    541   }
    542   if (TerminalAttChange) {
    543     Var_UpdateConsoleInpOption ();
    544     Var_UpdateConsoleOutOption ();
    545     Var_UpdateErrorOutOption ();
    546   }
    547 
    548   //
    549   // Check data which located in Console Options Menu and save the settings if need
    550   //
    551   if (CompareMem (NewBmmData->ConsoleInCheck, OldBmmData->ConsoleInCheck, sizeof (NewBmmData->ConsoleInCheck)) != 0) {
    552     for (Index = 0; Index < ConsoleInpMenu.MenuNumber; Index++) {
    553       NewMenuEntry                = BOpt_GetMenuEntry (&ConsoleInpMenu, Index);
    554       NewConsoleContext           = (BM_CONSOLE_CONTEXT *) NewMenuEntry->VariableContext;
    555       ASSERT (Index < MAX_MENU_NUMBER);
    556       NewConsoleContext->IsActive = NewBmmData->ConsoleInCheck[Index];
    557     }
    558 
    559     Var_UpdateConsoleInpOption ();
    560   }
    561 
    562   if (CompareMem (NewBmmData->ConsoleOutCheck, OldBmmData->ConsoleOutCheck, sizeof (NewBmmData->ConsoleOutCheck)) != 0) {
    563     for (Index = 0; Index < ConsoleOutMenu.MenuNumber; Index++) {
    564       NewMenuEntry                = BOpt_GetMenuEntry (&ConsoleOutMenu, Index);
    565       NewConsoleContext           = (BM_CONSOLE_CONTEXT *) NewMenuEntry->VariableContext;
    566       ASSERT (Index < MAX_MENU_NUMBER);
    567       NewConsoleContext->IsActive = NewBmmData->ConsoleOutCheck[Index];
    568     }
    569 
    570     Var_UpdateConsoleOutOption ();
    571   }
    572 
    573   if (CompareMem (NewBmmData->ConsoleErrCheck, OldBmmData->ConsoleErrCheck, sizeof (NewBmmData->ConsoleErrCheck)) != 0) {
    574     for (Index = 0; Index < ConsoleErrMenu.MenuNumber; Index++) {
    575       NewMenuEntry                = BOpt_GetMenuEntry (&ConsoleErrMenu, Index);
    576       NewConsoleContext           = (BM_CONSOLE_CONTEXT *) NewMenuEntry->VariableContext;
    577       ASSERT (Index < MAX_MENU_NUMBER);
    578       NewConsoleContext->IsActive = NewBmmData->ConsoleErrCheck[Index];
    579     }
    580 
    581     Var_UpdateErrorOutOption ();
    582   }
    583 
    584   //
    585   // After user do the save action, need to update OldBmmData.
    586   //
    587   CopyMem (OldBmmData, NewBmmData, sizeof (BMM_FAKE_NV_DATA));
    588 
    589   return EFI_SUCCESS;
    590 }
    591 
    592 /**
    593   Create GoTo OP code into FORM_BOOT_LEGACY_DEVICE label for legacy boot option.
    594 
    595 **/
    596 EFI_STATUS
    597 InitializeLegacyBootOption (
    598   VOID
    599   )
    600 {
    601   RefreshUpdateData ();
    602   mStartLabel->Number = FORM_BOOT_LEGACY_DEVICE_ID;
    603 
    604   //
    605   // If LegacyBios Protocol is installed, add 3 tags about legacy boot option
    606   // in BootOption form: legacy FD/HD/CD/NET/BEV
    607   //
    608   HiiCreateGotoOpCode (
    609     mStartOpCodeHandle,
    610     FORM_SET_FD_ORDER_ID,
    611     STRING_TOKEN (STR_FORM_SET_FD_ORDER_TITLE),
    612     STRING_TOKEN (STR_FORM_SET_FD_ORDER_TITLE),
    613     EFI_IFR_FLAG_CALLBACK,
    614     FORM_SET_FD_ORDER_ID
    615     );
    616 
    617   HiiCreateGotoOpCode (
    618     mStartOpCodeHandle,
    619     FORM_SET_HD_ORDER_ID,
    620     STRING_TOKEN (STR_FORM_SET_HD_ORDER_TITLE),
    621     STRING_TOKEN (STR_FORM_SET_HD_ORDER_TITLE),
    622     EFI_IFR_FLAG_CALLBACK,
    623     FORM_SET_HD_ORDER_ID
    624     );
    625 
    626   HiiCreateGotoOpCode (
    627     mStartOpCodeHandle,
    628     FORM_SET_CD_ORDER_ID,
    629     STRING_TOKEN (STR_FORM_SET_CD_ORDER_TITLE),
    630     STRING_TOKEN (STR_FORM_SET_CD_ORDER_TITLE),
    631     EFI_IFR_FLAG_CALLBACK,
    632     FORM_SET_CD_ORDER_ID
    633     );
    634 
    635   HiiCreateGotoOpCode (
    636     mStartOpCodeHandle,
    637     FORM_SET_NET_ORDER_ID,
    638     STRING_TOKEN (STR_FORM_SET_NET_ORDER_TITLE),
    639     STRING_TOKEN (STR_FORM_SET_NET_ORDER_TITLE),
    640     EFI_IFR_FLAG_CALLBACK,
    641     FORM_SET_NET_ORDER_ID
    642     );
    643 
    644   HiiCreateGotoOpCode (
    645     mStartOpCodeHandle,
    646     FORM_SET_BEV_ORDER_ID,
    647     STRING_TOKEN (STR_FORM_SET_BEV_ORDER_TITLE),
    648     STRING_TOKEN (STR_FORM_SET_BEV_ORDER_TITLE),
    649     EFI_IFR_FLAG_CALLBACK,
    650     FORM_SET_BEV_ORDER_ID
    651     );
    652 
    653   HiiUpdateForm (
    654     mBmmCallbackInfo->BmmHiiHandle,
    655     &gBootMaintFormSetGuid,
    656     FORM_BOOT_SETUP_ID,
    657     mStartOpCodeHandle, // Label FORM_BOOT_LEGACY_DEVICE_ID
    658     mEndOpCodeHandle    // LABEL_END
    659     );
    660 
    661   return EFI_SUCCESS;
    662 }
    663 
    664 /**
    665   This function processes the results of changes in configuration.
    666 
    667 
    668   @param This               Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
    669   @param Action             Specifies the type of action taken by the browser.
    670   @param QuestionId         A unique value which is sent to the original exporting driver
    671                             so that it can identify the type of data to expect.
    672   @param Type               The type of value for the question.
    673   @param Value              A pointer to the data being sent to the original exporting driver.
    674   @param ActionRequest      On return, points to the action requested by the callback function.
    675 
    676   @retval EFI_SUCCESS           The callback successfully handled the action.
    677   @retval EFI_OUT_OF_RESOURCES  Not enough storage is available to hold the variable and its data.
    678   @retval EFI_DEVICE_ERROR      The variable could not be saved.
    679   @retval EFI_UNSUPPORTED       The specified Action is not supported by the callback.
    680   @retval EFI_INVALID_PARAMETER The parameter of Value or ActionRequest is invalid.
    681 **/
    682 EFI_STATUS
    683 EFIAPI
    684 BootMaintCallback (
    685   IN  CONST EFI_HII_CONFIG_ACCESS_PROTOCOL         *This,
    686   IN        EFI_BROWSER_ACTION                     Action,
    687   IN        EFI_QUESTION_ID                        QuestionId,
    688   IN        UINT8                                  Type,
    689   IN        EFI_IFR_TYPE_VALUE                     *Value,
    690   OUT       EFI_BROWSER_ACTION_REQUEST             *ActionRequest
    691   )
    692 {
    693   BMM_CALLBACK_DATA *Private;
    694   BM_MENU_ENTRY     *NewMenuEntry;
    695   BMM_FAKE_NV_DATA  *CurrentFakeNVMap;
    696   EFI_STATUS        Status;
    697   UINTN             OldValue;
    698   UINTN             NewValue;
    699   UINTN             Number;
    700   UINTN             Pos;
    701   UINTN             Bit;
    702   UINT16            NewValuePos;
    703   UINT16            Index3;
    704   UINT16            Index2;
    705   UINT16            Index;
    706   UINT8             *OldLegacyDev;
    707   UINT8             *NewLegacyDev;
    708   UINT8             *DisMap;
    709   EFI_LEGACY_BIOS_PROTOCOL    *LegacyBios;
    710 
    711   Private = BMM_CALLBACK_DATA_FROM_THIS (This);
    712   if (Action == EFI_BROWSER_ACTION_FORM_OPEN && QuestionId == FORM_BOOT_SETUP_ID) {
    713     //
    714     // Initilize Form for legacy boot option.
    715     //
    716     Status = EfiLibLocateProtocol (&gEfiLegacyBiosProtocolGuid, (VOID **) &LegacyBios);
    717     if (!EFI_ERROR (Status)) {
    718       InitializeLegacyBootOption ();
    719     }
    720 
    721     return EFI_SUCCESS;
    722   }
    723 
    724   if (Action != EFI_BROWSER_ACTION_CHANGING && Action != EFI_BROWSER_ACTION_CHANGED) {
    725     //
    726     // All other action return unsupported.
    727     //
    728     return EFI_UNSUPPORTED;
    729   }
    730 
    731   Status       = EFI_SUCCESS;
    732   OldValue     = 0;
    733   NewValue     = 0;
    734   Number       = 0;
    735   OldLegacyDev = NULL;
    736   NewLegacyDev = NULL;
    737   NewValuePos  = 0;
    738   DisMap       = NULL;
    739 
    740   Private      = BMM_CALLBACK_DATA_FROM_THIS (This);
    741   //
    742   // Retrieve uncommitted data from Form Browser
    743   //
    744   CurrentFakeNVMap = &Private->BmmFakeNvData;
    745   HiiGetBrowserData (&gBootMaintFormSetGuid, mBootMaintStorageName, sizeof (BMM_FAKE_NV_DATA), (UINT8 *) CurrentFakeNVMap);
    746   if (Action == EFI_BROWSER_ACTION_CHANGING) {
    747     if (Value == NULL) {
    748       return EFI_INVALID_PARAMETER;
    749     }
    750 
    751     UpdatePageId (Private, QuestionId);
    752 
    753     if (QuestionId < FILE_OPTION_OFFSET) {
    754       if (QuestionId < CONFIG_OPTION_OFFSET) {
    755         switch (QuestionId) {
    756         case KEY_VALUE_BOOT_FROM_FILE:
    757           Private->FeCurrentState = FileExplorerStateBootFromFile;
    758           break;
    759 
    760         case FORM_BOOT_ADD_ID:
    761           Private->FeCurrentState = FileExplorerStateAddBootOption;
    762           break;
    763 
    764         case FORM_DRV_ADD_FILE_ID:
    765           Private->FeCurrentState = FileExplorerStateAddDriverOptionState;
    766           break;
    767 
    768         case FORM_DRV_ADD_HANDLE_ID:
    769           CleanUpPage (FORM_DRV_ADD_HANDLE_ID, Private);
    770           UpdateDrvAddHandlePage (Private);
    771           break;
    772 
    773         case FORM_BOOT_DEL_ID:
    774           CleanUpPage (FORM_BOOT_DEL_ID, Private);
    775           UpdateBootDelPage (Private);
    776           break;
    777 
    778         case FORM_BOOT_CHG_ID:
    779         case FORM_DRV_CHG_ID:
    780           UpdatePageBody (QuestionId, Private);
    781           break;
    782 
    783         case FORM_DRV_DEL_ID:
    784           CleanUpPage (FORM_DRV_DEL_ID, Private);
    785           UpdateDrvDelPage (Private);
    786           break;
    787 
    788         case FORM_BOOT_NEXT_ID:
    789           CleanUpPage (FORM_BOOT_NEXT_ID, Private);
    790           UpdateBootNextPage (Private);
    791           break;
    792 
    793         case FORM_TIME_OUT_ID:
    794           CleanUpPage (FORM_TIME_OUT_ID, Private);
    795           UpdateTimeOutPage (Private);
    796           break;
    797 
    798         case FORM_CON_IN_ID:
    799         case FORM_CON_OUT_ID:
    800         case FORM_CON_ERR_ID:
    801           UpdatePageBody (QuestionId, Private);
    802           break;
    803 
    804         case FORM_CON_MODE_ID:
    805           CleanUpPage (FORM_CON_MODE_ID, Private);
    806           UpdateConModePage (Private);
    807           break;
    808 
    809         case FORM_CON_COM_ID:
    810           CleanUpPage (FORM_CON_COM_ID, Private);
    811           UpdateConCOMPage (Private);
    812           break;
    813 
    814         case FORM_SET_FD_ORDER_ID:
    815         case FORM_SET_HD_ORDER_ID:
    816         case FORM_SET_CD_ORDER_ID:
    817         case FORM_SET_NET_ORDER_ID:
    818         case FORM_SET_BEV_ORDER_ID:
    819           CleanUpPage (QuestionId, Private);
    820           UpdateSetLegacyDeviceOrderPage (QuestionId, Private);
    821           break;
    822 
    823         default:
    824           break;
    825         }
    826       } else if ((QuestionId >= TERMINAL_OPTION_OFFSET) && (QuestionId < CONSOLE_OPTION_OFFSET)) {
    827         Index2                    = (UINT16) (QuestionId - TERMINAL_OPTION_OFFSET);
    828         Private->CurrentTerminal  = Index2;
    829 
    830         CleanUpPage (FORM_CON_COM_SETUP_ID, Private);
    831         UpdateTerminalPage (Private);
    832 
    833       } else if (QuestionId >= HANDLE_OPTION_OFFSET) {
    834         Index2                  = (UINT16) (QuestionId - HANDLE_OPTION_OFFSET);
    835 
    836         NewMenuEntry            = BOpt_GetMenuEntry (&DriverMenu, Index2);
    837         ASSERT (NewMenuEntry != NULL);
    838         Private->HandleContext  = (BM_HANDLE_CONTEXT *) NewMenuEntry->VariableContext;
    839 
    840         CleanUpPage (FORM_DRV_ADD_HANDLE_DESC_ID, Private);
    841 
    842         Private->MenuEntry                  = NewMenuEntry;
    843         Private->LoadContext->FilePathList  = Private->HandleContext->DevicePath;
    844 
    845         UpdateDriverAddHandleDescPage (Private);
    846       }
    847     }
    848   } else if (Action == EFI_BROWSER_ACTION_CHANGED) {
    849     if ((Value == NULL) || (ActionRequest == NULL)) {
    850       return EFI_INVALID_PARAMETER;
    851     }
    852     if ((QuestionId >= BOOT_OPTION_DEL_QUESTION_ID) && (QuestionId < BOOT_OPTION_DEL_QUESTION_ID + MAX_MENU_NUMBER)) {
    853       if (Value->b){
    854         //
    855         // Means user try to delete this boot option but not press F10 or "Commit Changes and Exit" menu.
    856         //
    857         CurrentFakeNVMap->BootOptionDelMark[QuestionId - BOOT_OPTION_DEL_QUESTION_ID] = TRUE;
    858       } else {
    859         //
    860         // Means user remove the old check status.
    861         //
    862         CurrentFakeNVMap->BootOptionDelMark[QuestionId - BOOT_OPTION_DEL_QUESTION_ID] = FALSE;
    863       }
    864     } else if ((QuestionId >= DRIVER_OPTION_DEL_QUESTION_ID) && (QuestionId < DRIVER_OPTION_DEL_QUESTION_ID + MAX_MENU_NUMBER)) {
    865       if (Value->b){
    866         CurrentFakeNVMap->DriverOptionDelMark[QuestionId - DRIVER_OPTION_DEL_QUESTION_ID] = TRUE;
    867       } else {
    868         CurrentFakeNVMap->DriverOptionDelMark[QuestionId - DRIVER_OPTION_DEL_QUESTION_ID] = FALSE;
    869       }
    870     } else if ((QuestionId >= LEGACY_FD_QUESTION_ID) && (QuestionId < LEGACY_BEV_QUESTION_ID + MAX_MENU_NUMBER)) {
    871       //
    872       // Update Select FD/HD/CD/NET/BEV Order Form
    873       //
    874 
    875       DisMap  = Private->BmmOldFakeNVData.DisableMap;
    876 
    877       if (QuestionId >= LEGACY_FD_QUESTION_ID && QuestionId < LEGACY_FD_QUESTION_ID + MAX_MENU_NUMBER) {
    878         Number        = (UINT16) LegacyFDMenu.MenuNumber;
    879         OldLegacyDev  = Private->BmmOldFakeNVData.LegacyFD;
    880         NewLegacyDev  = CurrentFakeNVMap->LegacyFD;
    881       } else if (QuestionId >= LEGACY_HD_QUESTION_ID && QuestionId < LEGACY_HD_QUESTION_ID + MAX_MENU_NUMBER) {
    882         Number        = (UINT16) LegacyHDMenu.MenuNumber;
    883         OldLegacyDev  = Private->BmmOldFakeNVData.LegacyHD;
    884         NewLegacyDev  = CurrentFakeNVMap->LegacyHD;
    885       } else if (QuestionId >= LEGACY_CD_QUESTION_ID && QuestionId < LEGACY_CD_QUESTION_ID + MAX_MENU_NUMBER) {
    886         Number        = (UINT16) LegacyCDMenu.MenuNumber;
    887         OldLegacyDev  = Private->BmmOldFakeNVData.LegacyCD;
    888         NewLegacyDev  = CurrentFakeNVMap->LegacyCD;
    889       } else if (QuestionId >= LEGACY_NET_QUESTION_ID && QuestionId < LEGACY_NET_QUESTION_ID + MAX_MENU_NUMBER) {
    890         Number        = (UINT16) LegacyNETMenu.MenuNumber;
    891         OldLegacyDev  = Private->BmmOldFakeNVData.LegacyNET;
    892         NewLegacyDev  = CurrentFakeNVMap->LegacyNET;
    893       } else if (QuestionId >= LEGACY_BEV_QUESTION_ID && QuestionId < LEGACY_BEV_QUESTION_ID + MAX_MENU_NUMBER) {
    894         Number        = (UINT16) LegacyBEVMenu.MenuNumber;
    895         OldLegacyDev  = Private->BmmOldFakeNVData.LegacyBEV;
    896         NewLegacyDev  = CurrentFakeNVMap->LegacyBEV;
    897       }
    898       //
    899       //  First, find the different position
    900       //  if there is change, it should be only one
    901       //
    902       for (Index = 0; Index < Number; Index++) {
    903         if (OldLegacyDev[Index] != NewLegacyDev[Index]) {
    904           OldValue  = OldLegacyDev[Index];
    905           NewValue  = NewLegacyDev[Index];
    906           break;
    907         }
    908       }
    909 
    910       if (Index != Number) {
    911         //
    912         // there is change, now process
    913         //
    914         if (0xFF == NewValue) {
    915           //
    916           // This item will be disable
    917           // Just move the items behind this forward to overlap it
    918           //
    919           Pos = OldValue / 8;
    920           Bit = 7 - (OldValue % 8);
    921           DisMap[Pos] = (UINT8) (DisMap[Pos] | (UINT8) (1 << Bit));
    922           for (Index2 = Index; Index2 < Number - 1; Index2++) {
    923             NewLegacyDev[Index2] = NewLegacyDev[Index2 + 1];
    924           }
    925 
    926           NewLegacyDev[Index2] = 0xFF;
    927         } else {
    928           for (Index2 = 0; Index2 < Number; Index2++) {
    929             if (Index2 == Index) {
    930               continue;
    931             }
    932 
    933             if (OldLegacyDev[Index2] == NewValue) {
    934               //
    935               // If NewValue is in OldLegacyDev array
    936               // remember its old position
    937               //
    938               NewValuePos = Index2;
    939               break;
    940             }
    941           }
    942 
    943           if (Index2 != Number) {
    944             //
    945             // We will change current item to an existing item
    946             // (It's hard to describe here, please read code, it's like a cycle-moving)
    947             //
    948             for (Index2 = NewValuePos; Index2 != Index;) {
    949               if (NewValuePos < Index) {
    950                 NewLegacyDev[Index2] = OldLegacyDev[Index2 + 1];
    951                 Index2++;
    952               } else {
    953                 NewLegacyDev[Index2] = OldLegacyDev[Index2 - 1];
    954                 Index2--;
    955               }
    956             }
    957           } else {
    958             //
    959             // If NewValue is not in OldlegacyDev array, we are changing to a disabled item
    960             // so we should modify DisMap to reflect the change
    961             //
    962             Pos = NewValue / 8;
    963             Bit = 7 - (NewValue % 8);
    964             DisMap[Pos] = (UINT8) (DisMap[Pos] & (~ (UINT8) (1 << Bit)));
    965             if (0xFF != OldValue) {
    966               //
    967               // Because NewValue is a item that was disabled before
    968               // so after changing the OldValue should be disabled
    969               // actually we are doing a swap of enable-disable states of two items
    970               //
    971               Pos = OldValue / 8;
    972               Bit = 7 - (OldValue % 8);
    973               DisMap[Pos] = (UINT8) (DisMap[Pos] | (UINT8) (1 << Bit));
    974             }
    975           }
    976         }
    977         //
    978         // To prevent DISABLE appears in the middle of the list
    979         // we should perform a re-ordering
    980         //
    981         Index3 = Index;
    982         Index = 0;
    983         while (Index < Number) {
    984           if (0xFF != NewLegacyDev[Index]) {
    985             Index++;
    986             continue;
    987           }
    988 
    989           Index2 = Index;
    990           Index2++;
    991           while (Index2 < Number) {
    992             if (0xFF != NewLegacyDev[Index2]) {
    993               break;
    994             }
    995 
    996             Index2++;
    997           }
    998 
    999           if (Index2 < Number) {
   1000             NewLegacyDev[Index]   = NewLegacyDev[Index2];
   1001             NewLegacyDev[Index2]  = 0xFF;
   1002           }
   1003 
   1004           Index++;
   1005         }
   1006 
   1007         //
   1008         //  Return correct question value.
   1009         //
   1010         Value->u8 = NewLegacyDev[Index3];
   1011       }
   1012     } else {
   1013       switch (QuestionId) {
   1014       case KEY_VALUE_SAVE_AND_EXIT:
   1015         *ActionRequest = EFI_BROWSER_ACTION_REQUEST_FORM_SUBMIT_EXIT;
   1016         break;
   1017 
   1018       case KEY_VALUE_NO_SAVE_AND_EXIT:
   1019         //
   1020         // Restore local maintain data.
   1021         //
   1022         DiscardChangeHandler (Private, CurrentFakeNVMap);
   1023         *ActionRequest = EFI_BROWSER_ACTION_REQUEST_FORM_DISCARD_EXIT;
   1024         break;
   1025 
   1026       case FORM_RESET:
   1027         gRT->ResetSystem (EfiResetCold, EFI_SUCCESS, 0, NULL);
   1028         return EFI_UNSUPPORTED;
   1029 
   1030       default:
   1031         break;
   1032       }
   1033     }
   1034   }
   1035 
   1036   //
   1037   // Pass changed uncommitted data back to Form Browser
   1038   //
   1039   HiiSetBrowserData (&gBootMaintFormSetGuid, mBootMaintStorageName, sizeof (BMM_FAKE_NV_DATA), (UINT8 *) CurrentFakeNVMap, NULL);
   1040   return EFI_SUCCESS;
   1041 }
   1042 
   1043 /**
   1044   Discard all changes done to the BMM pages such as Boot Order change,
   1045   Driver order change.
   1046 
   1047   @param Private            The BMM context data.
   1048   @param CurrentFakeNVMap   The current Fack NV Map.
   1049 
   1050 **/
   1051 VOID
   1052 DiscardChangeHandler (
   1053   IN  BMM_CALLBACK_DATA               *Private,
   1054   IN  BMM_FAKE_NV_DATA                *CurrentFakeNVMap
   1055   )
   1056 {
   1057   UINT16  Index;
   1058 
   1059   switch (Private->BmmPreviousPageId) {
   1060   case FORM_BOOT_CHG_ID:
   1061     CopyMem (CurrentFakeNVMap->BootOptionOrder, Private->BmmOldFakeNVData.BootOptionOrder, sizeof (CurrentFakeNVMap->BootOptionOrder));
   1062     break;
   1063 
   1064   case FORM_DRV_CHG_ID:
   1065     CopyMem (CurrentFakeNVMap->DriverOptionOrder, Private->BmmOldFakeNVData.DriverOptionOrder, sizeof (CurrentFakeNVMap->DriverOptionOrder));
   1066     break;
   1067 
   1068   case FORM_BOOT_DEL_ID:
   1069     ASSERT (BootOptionMenu.MenuNumber <= (sizeof (CurrentFakeNVMap->BootOptionDel) / sizeof (CurrentFakeNVMap->BootOptionDel[0])));
   1070     for (Index = 0; Index < BootOptionMenu.MenuNumber; Index++) {
   1071       CurrentFakeNVMap->BootOptionDel[Index] = FALSE;
   1072       CurrentFakeNVMap->BootOptionDelMark[Index] = FALSE;
   1073     }
   1074     break;
   1075 
   1076   case FORM_DRV_DEL_ID:
   1077     ASSERT (DriverOptionMenu.MenuNumber <= (sizeof (CurrentFakeNVMap->DriverOptionDel) / sizeof (CurrentFakeNVMap->DriverOptionDel[0])));
   1078     for (Index = 0; Index < DriverOptionMenu.MenuNumber; Index++) {
   1079       CurrentFakeNVMap->DriverOptionDel[Index] = FALSE;
   1080       CurrentFakeNVMap->DriverOptionDelMark[Index] = FALSE;
   1081     }
   1082     break;
   1083 
   1084   case FORM_BOOT_NEXT_ID:
   1085     CurrentFakeNVMap->BootNext = Private->BmmOldFakeNVData.BootNext;
   1086     break;
   1087 
   1088   case FORM_TIME_OUT_ID:
   1089     CurrentFakeNVMap->BootTimeOut = Private->BmmOldFakeNVData.BootTimeOut;
   1090     break;
   1091 
   1092   case FORM_DRV_ADD_HANDLE_DESC_ID:
   1093   case FORM_DRV_ADD_FILE_ID:
   1094   case FORM_DRV_ADD_HANDLE_ID:
   1095     CurrentFakeNVMap->DriverAddHandleDesc[0]          = 0x0000;
   1096     CurrentFakeNVMap->DriverAddHandleOptionalData[0]  = 0x0000;
   1097     break;
   1098 
   1099   default:
   1100     break;
   1101   }
   1102 }
   1103 
   1104 /**
   1105   Initialize the Boot Maintenance Utitliy.
   1106 
   1107 
   1108   @retval  EFI_SUCCESS      utility ended successfully
   1109   @retval  others           contain some errors
   1110 
   1111 **/
   1112 EFI_STATUS
   1113 InitializeBM (
   1114   VOID
   1115   )
   1116 {
   1117   BMM_CALLBACK_DATA           *BmmCallbackInfo;
   1118   EFI_STATUS                  Status;
   1119   EFI_HII_PACKAGE_LIST_HEADER *PackageListHeader;
   1120   UINT32                      Length;
   1121   UINT8                       *Data;
   1122 
   1123   Status = EFI_SUCCESS;
   1124   BmmCallbackInfo = mBmmCallbackInfo;
   1125 
   1126   BmmCallbackInfo->BmmPreviousPageId             = FORM_MAIN_ID;
   1127   BmmCallbackInfo->BmmCurrentPageId              = FORM_MAIN_ID;
   1128   BmmCallbackInfo->FeCurrentState                = FileExplorerStateInActive;
   1129   BmmCallbackInfo->FeDisplayContext              = FileExplorerDisplayUnknown;
   1130 
   1131   //
   1132   // Reinstall String packages to include more new strings.
   1133   //
   1134 
   1135   //
   1136   // String package size
   1137   //
   1138   Length = ReadUnaligned32 ((UINT32 *) BdsDxeStrings) - sizeof (UINT32);
   1139 
   1140   //
   1141   // Add the length of the Package List Header and the terminating Package Header
   1142   //
   1143   Length += sizeof (EFI_HII_PACKAGE_LIST_HEADER) + sizeof (EFI_HII_PACKAGE_HEADER);
   1144 
   1145   //
   1146   // Allocate the storage for the entire Package List
   1147   //
   1148   PackageListHeader = AllocateZeroPool (Length);
   1149 
   1150   //
   1151   // If the Package List can not be allocated, then return a NULL HII Handle
   1152   //
   1153   if (PackageListHeader == NULL) {
   1154     return EFI_OUT_OF_RESOURCES;
   1155   }
   1156 
   1157   //
   1158   // Fill in the GUID and Length of the Package List Header
   1159   //
   1160   PackageListHeader->PackageLength = Length;
   1161 
   1162   //
   1163   // Copy String Data into Package list.
   1164   //
   1165   Data = (UINT8 *)(PackageListHeader + 1);
   1166   Length = ReadUnaligned32 ((UINT32 *) BdsDxeStrings) - sizeof (UINT32);
   1167   CopyMem (Data, (UINT8 *) BdsDxeStrings + sizeof (UINT32), Length);
   1168 
   1169   //
   1170   // Add End type HII package.
   1171   //
   1172   Data += Length;
   1173   ((EFI_HII_PACKAGE_HEADER *) Data)->Type   = EFI_HII_PACKAGE_END;
   1174   ((EFI_HII_PACKAGE_HEADER *) Data)->Length = sizeof (EFI_HII_PACKAGE_HEADER);
   1175 
   1176   //
   1177   // Update String package for BM
   1178   //
   1179   CopyGuid (&PackageListHeader->PackageListGuid, &gBootMaintFormSetGuid);
   1180   Status = gHiiDatabase->UpdatePackageList (gHiiDatabase, BmmCallbackInfo->BmmHiiHandle, PackageListHeader);
   1181 
   1182   //
   1183   // Update String package for FE.
   1184   //
   1185   CopyGuid (&PackageListHeader->PackageListGuid, &gFileExploreFormSetGuid);
   1186   Status = gHiiDatabase->UpdatePackageList (gHiiDatabase, BmmCallbackInfo->FeHiiHandle, PackageListHeader);
   1187 
   1188   FreePool (PackageListHeader);
   1189 
   1190   //
   1191   // Init OpCode Handle and Allocate space for creation of Buffer
   1192   //
   1193   mStartOpCodeHandle = HiiAllocateOpCodeHandle ();
   1194   if (mStartOpCodeHandle == NULL) {
   1195     Status = EFI_OUT_OF_RESOURCES;
   1196     goto Exit;
   1197   }
   1198 
   1199   mEndOpCodeHandle = HiiAllocateOpCodeHandle ();
   1200   if (mEndOpCodeHandle == NULL) {
   1201     Status = EFI_OUT_OF_RESOURCES;
   1202     goto Exit;
   1203   }
   1204 
   1205   //
   1206   // Create Hii Extend Label OpCode as the start opcode
   1207   //
   1208   mStartLabel = (EFI_IFR_GUID_LABEL *) HiiCreateGuidOpCode (mStartOpCodeHandle, &gEfiIfrTianoGuid, NULL, sizeof (EFI_IFR_GUID_LABEL));
   1209   mStartLabel->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL;
   1210 
   1211   //
   1212   // Create Hii Extend Label OpCode as the end opcode
   1213   //
   1214   mEndLabel = (EFI_IFR_GUID_LABEL *) HiiCreateGuidOpCode (mEndOpCodeHandle, &gEfiIfrTianoGuid, NULL, sizeof (EFI_IFR_GUID_LABEL));
   1215   mEndLabel->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL;
   1216   mEndLabel->Number       = LABEL_END;
   1217 
   1218   InitializeStringDepository ();
   1219 
   1220   InitAllMenu (BmmCallbackInfo);
   1221 
   1222   CreateMenuStringToken (BmmCallbackInfo, BmmCallbackInfo->BmmHiiHandle, &ConsoleInpMenu);
   1223   CreateMenuStringToken (BmmCallbackInfo, BmmCallbackInfo->BmmHiiHandle, &ConsoleOutMenu);
   1224   CreateMenuStringToken (BmmCallbackInfo, BmmCallbackInfo->BmmHiiHandle, &ConsoleErrMenu);
   1225   CreateMenuStringToken (BmmCallbackInfo, BmmCallbackInfo->BmmHiiHandle, &BootOptionMenu);
   1226   CreateMenuStringToken (BmmCallbackInfo, BmmCallbackInfo->BmmHiiHandle, &DriverOptionMenu);
   1227   CreateMenuStringToken (BmmCallbackInfo, BmmCallbackInfo->BmmHiiHandle, &TerminalMenu);
   1228   CreateMenuStringToken (BmmCallbackInfo, BmmCallbackInfo->BmmHiiHandle, &DriverMenu);
   1229 
   1230   InitializeBmmConfig (BmmCallbackInfo);
   1231 
   1232   //
   1233   // Dispatch BMM main formset and File Explorer formset.
   1234   //
   1235   FormSetDispatcher (BmmCallbackInfo);
   1236 
   1237   //
   1238   // Clean up.
   1239   //
   1240   CleanUpStringDepository ();
   1241 
   1242   FreeAllMenu ();
   1243 
   1244 Exit:
   1245   if (mStartOpCodeHandle != NULL) {
   1246     HiiFreeOpCodeHandle (mStartOpCodeHandle);
   1247   }
   1248 
   1249   if (mEndOpCodeHandle != NULL) {
   1250     HiiFreeOpCodeHandle (mEndOpCodeHandle);
   1251   }
   1252 
   1253   return Status;
   1254 }
   1255 
   1256 
   1257 /**
   1258   Initialized all Menu Option List.
   1259 
   1260   @param CallbackData    The BMM context data.
   1261 
   1262 **/
   1263 VOID
   1264 InitAllMenu (
   1265   IN  BMM_CALLBACK_DATA    *CallbackData
   1266   )
   1267 {
   1268   InitializeListHead (&BootOptionMenu.Head);
   1269   InitializeListHead (&DriverOptionMenu.Head);
   1270   BOpt_GetBootOptions (CallbackData);
   1271   BOpt_GetDriverOptions (CallbackData);
   1272   BOpt_GetLegacyOptions ();
   1273   InitializeListHead (&FsOptionMenu.Head);
   1274   BOpt_FindDrivers ();
   1275   InitializeListHead (&DirectoryMenu.Head);
   1276   InitializeListHead (&ConsoleInpMenu.Head);
   1277   InitializeListHead (&ConsoleOutMenu.Head);
   1278   InitializeListHead (&ConsoleErrMenu.Head);
   1279   InitializeListHead (&TerminalMenu.Head);
   1280   LocateSerialIo ();
   1281   GetAllConsoles ();
   1282 }
   1283 
   1284 /**
   1285   Free up all Menu Option list.
   1286 
   1287 **/
   1288 VOID
   1289 FreeAllMenu (
   1290   VOID
   1291   )
   1292 {
   1293   BOpt_FreeMenu (&DirectoryMenu);
   1294   BOpt_FreeMenu (&FsOptionMenu);
   1295   BOpt_FreeMenu (&BootOptionMenu);
   1296   BOpt_FreeMenu (&DriverOptionMenu);
   1297   BOpt_FreeMenu (&DriverMenu);
   1298   BOpt_FreeLegacyOptions ();
   1299   FreeAllConsoles ();
   1300 }
   1301 
   1302 /**
   1303   Initialize all the string depositories.
   1304 
   1305 **/
   1306 VOID
   1307 InitializeStringDepository (
   1308   VOID
   1309   )
   1310 {
   1311   STRING_DEPOSITORY *StringDepository;
   1312   StringDepository              = AllocateZeroPool (sizeof (STRING_DEPOSITORY) * STRING_DEPOSITORY_NUMBER);
   1313   FileOptionStrDepository       = StringDepository++;
   1314   ConsoleOptionStrDepository    = StringDepository++;
   1315   BootOptionStrDepository       = StringDepository++;
   1316   BootOptionHelpStrDepository   = StringDepository++;
   1317   DriverOptionStrDepository     = StringDepository++;
   1318   DriverOptionHelpStrDepository = StringDepository++;
   1319   TerminalStrDepository         = StringDepository;
   1320 }
   1321 
   1322 /**
   1323   Fetch a usable string node from the string depository and return the string token.
   1324 
   1325   @param CallbackData       The BMM context data.
   1326   @param StringDepository   The string repository.
   1327 
   1328   @retval  EFI_STRING_ID           String token.
   1329 
   1330 **/
   1331 EFI_STRING_ID
   1332 GetStringTokenFromDepository (
   1333   IN   BMM_CALLBACK_DATA     *CallbackData,
   1334   IN   STRING_DEPOSITORY     *StringDepository
   1335   )
   1336 {
   1337   STRING_LIST_NODE  *CurrentListNode;
   1338   STRING_LIST_NODE  *NextListNode;
   1339 
   1340   CurrentListNode = StringDepository->CurrentNode;
   1341 
   1342   if ((NULL != CurrentListNode) && (NULL != CurrentListNode->Next)) {
   1343     //
   1344     // Fetch one reclaimed node from the list.
   1345     //
   1346     NextListNode = StringDepository->CurrentNode->Next;
   1347   } else {
   1348     //
   1349     // If there is no usable node in the list, update the list.
   1350     //
   1351     NextListNode = AllocateZeroPool (sizeof (STRING_LIST_NODE));
   1352     ASSERT (NextListNode != NULL);
   1353     NextListNode->StringToken = HiiSetString (CallbackData->BmmHiiHandle, 0, L" ", NULL);
   1354     ASSERT (NextListNode->StringToken != 0);
   1355 
   1356     StringDepository->TotalNodeNumber++;
   1357 
   1358     if (NULL == CurrentListNode) {
   1359       StringDepository->ListHead = NextListNode;
   1360     } else {
   1361       CurrentListNode->Next = NextListNode;
   1362     }
   1363   }
   1364 
   1365   StringDepository->CurrentNode = NextListNode;
   1366 
   1367   return StringDepository->CurrentNode->StringToken;
   1368 }
   1369 
   1370 /**
   1371   Reclaim string depositories by moving the current node pointer to list head..
   1372 
   1373 **/
   1374 VOID
   1375 ReclaimStringDepository (
   1376   VOID
   1377   )
   1378 {
   1379   UINTN             DepositoryIndex;
   1380   STRING_DEPOSITORY *StringDepository;
   1381 
   1382   StringDepository = FileOptionStrDepository;
   1383   for (DepositoryIndex = 0; DepositoryIndex < STRING_DEPOSITORY_NUMBER; DepositoryIndex++) {
   1384     StringDepository->CurrentNode = StringDepository->ListHead;
   1385     StringDepository++;
   1386   }
   1387 }
   1388 
   1389 /**
   1390   Release resource for all the string depositories.
   1391 
   1392 **/
   1393 VOID
   1394 CleanUpStringDepository (
   1395   VOID
   1396   )
   1397 {
   1398   UINTN             NodeIndex;
   1399   UINTN             DepositoryIndex;
   1400   STRING_LIST_NODE  *CurrentListNode;
   1401   STRING_LIST_NODE  *NextListNode;
   1402   STRING_DEPOSITORY *StringDepository;
   1403 
   1404   //
   1405   // Release string list nodes.
   1406   //
   1407   StringDepository = FileOptionStrDepository;
   1408   for (DepositoryIndex = 0; DepositoryIndex < STRING_DEPOSITORY_NUMBER; DepositoryIndex++) {
   1409     CurrentListNode = StringDepository->ListHead;
   1410     for (NodeIndex = 0; NodeIndex < StringDepository->TotalNodeNumber; NodeIndex++) {
   1411       NextListNode = CurrentListNode->Next;
   1412       FreePool (CurrentListNode);
   1413       CurrentListNode = NextListNode;
   1414     }
   1415 
   1416     StringDepository++;
   1417   }
   1418   //
   1419   // Release string depository.
   1420   //
   1421   FreePool (FileOptionStrDepository);
   1422 }
   1423 
   1424 /**
   1425   Start boot maintenance manager
   1426 
   1427   @retval EFI_SUCCESS If BMM is invoked successfully.
   1428   @return Other value if BMM return unsuccessfully.
   1429 
   1430 **/
   1431 EFI_STATUS
   1432 BdsStartBootMaint (
   1433   VOID
   1434   )
   1435 {
   1436   EFI_STATUS      Status;
   1437   LIST_ENTRY      BdsBootOptionList;
   1438 
   1439   InitializeListHead (&BdsBootOptionList);
   1440 
   1441   //
   1442   // Connect all prior to entering the platform setup menu.
   1443   //
   1444   if (!gConnectAllHappened) {
   1445     BdsLibConnectAllDriversToAllControllers ();
   1446     gConnectAllHappened = TRUE;
   1447   }
   1448   //
   1449   // Have chance to enumerate boot device
   1450   //
   1451   BdsLibEnumerateAllBootOption (&BdsBootOptionList);
   1452 
   1453   //
   1454   // Group the legacy boot options for the same device type
   1455   //
   1456   GroupMultipleLegacyBootOption4SameType ();
   1457 
   1458   //
   1459   // Init the BMM
   1460   //
   1461   Status = InitializeBM ();
   1462 
   1463   return Status;
   1464 }
   1465 
   1466 /**
   1467   Dispatch BMM formset and FileExplorer formset.
   1468 
   1469 
   1470   @param CallbackData    The BMM context data.
   1471 
   1472   @retval EFI_SUCCESS If function complete successfully.
   1473   @return Other value if the Setup Browser process BMM's pages and
   1474            return unsuccessfully.
   1475 
   1476 **/
   1477 EFI_STATUS
   1478 FormSetDispatcher (
   1479   IN  BMM_CALLBACK_DATA    *CallbackData
   1480   )
   1481 {
   1482   EFI_STATUS                 Status;
   1483   EFI_BROWSER_ACTION_REQUEST ActionRequest;
   1484 
   1485   while (TRUE) {
   1486     UpdatePageId (CallbackData, FORM_MAIN_ID);
   1487 
   1488     ActionRequest = EFI_BROWSER_ACTION_REQUEST_NONE;
   1489     Status = gFormBrowser2->SendForm (
   1490                              gFormBrowser2,
   1491                              &CallbackData->BmmHiiHandle,
   1492                              1,
   1493                              &gBootMaintFormSetGuid,
   1494                              0,
   1495                              NULL,
   1496                              &ActionRequest
   1497                              );
   1498     if (ActionRequest == EFI_BROWSER_ACTION_REQUEST_RESET) {
   1499       EnableResetRequired ();
   1500     }
   1501 
   1502     ReclaimStringDepository ();
   1503 
   1504     //
   1505     // When this Formset returns, check if we are going to explore files.
   1506     //
   1507     if (FileExplorerStateInActive != CallbackData->FeCurrentState) {
   1508       UpdateFileExplorer (CallbackData, 0);
   1509 
   1510       ActionRequest = EFI_BROWSER_ACTION_REQUEST_NONE;
   1511       Status = gFormBrowser2->SendForm (
   1512                                gFormBrowser2,
   1513                                &CallbackData->FeHiiHandle,
   1514                                1,
   1515                                &gFileExploreFormSetGuid,
   1516                                0,
   1517                                NULL,
   1518                                &ActionRequest
   1519                                );
   1520       if (ActionRequest == EFI_BROWSER_ACTION_REQUEST_RESET) {
   1521         EnableResetRequired ();
   1522       }
   1523 
   1524       CallbackData->FeCurrentState    = FileExplorerStateInActive;
   1525       CallbackData->FeDisplayContext  = FileExplorerDisplayUnknown;
   1526       ReclaimStringDepository ();
   1527     } else {
   1528       break;
   1529     }
   1530   }
   1531 
   1532   return Status;
   1533 }
   1534 
   1535 /**
   1536   Intall BootMaint and FileExplorer HiiPackages.
   1537 
   1538 **/
   1539 EFI_STATUS
   1540 InitBMPackage (
   1541   VOID
   1542   )
   1543 {
   1544   BMM_CALLBACK_DATA           *BmmCallbackInfo;
   1545   EFI_STATUS                  Status;
   1546   UINT8                       *Ptr;
   1547 
   1548   //
   1549   // Create CallbackData structures for Driver Callback
   1550   //
   1551   BmmCallbackInfo = AllocateZeroPool (sizeof (BMM_CALLBACK_DATA));
   1552   if (BmmCallbackInfo == NULL) {
   1553     return EFI_OUT_OF_RESOURCES;
   1554   }
   1555 
   1556   //
   1557   // Create LoadOption in BmmCallbackInfo for Driver Callback
   1558   //
   1559   Ptr = AllocateZeroPool (sizeof (BM_LOAD_CONTEXT) + sizeof (BM_FILE_CONTEXT) + sizeof (BM_HANDLE_CONTEXT) + sizeof (BM_MENU_ENTRY));
   1560   if (Ptr == NULL) {
   1561     FreePool (BmmCallbackInfo);
   1562     BmmCallbackInfo = NULL;
   1563     return EFI_OUT_OF_RESOURCES;
   1564   }
   1565   //
   1566   // Initialize Bmm callback data.
   1567   //
   1568   BmmCallbackInfo->LoadContext = (BM_LOAD_CONTEXT *) Ptr;
   1569   Ptr += sizeof (BM_LOAD_CONTEXT);
   1570 
   1571   BmmCallbackInfo->FileContext = (BM_FILE_CONTEXT *) Ptr;
   1572   Ptr += sizeof (BM_FILE_CONTEXT);
   1573 
   1574   BmmCallbackInfo->HandleContext = (BM_HANDLE_CONTEXT *) Ptr;
   1575   Ptr += sizeof (BM_HANDLE_CONTEXT);
   1576 
   1577   BmmCallbackInfo->MenuEntry      = (BM_MENU_ENTRY *) Ptr;
   1578 
   1579   BmmCallbackInfo->Signature                     = BMM_CALLBACK_DATA_SIGNATURE;
   1580   BmmCallbackInfo->BmmConfigAccess.ExtractConfig = BootMaintExtractConfig;
   1581   BmmCallbackInfo->BmmConfigAccess.RouteConfig   = BootMaintRouteConfig;
   1582   BmmCallbackInfo->BmmConfigAccess.Callback      = BootMaintCallback;
   1583   BmmCallbackInfo->FeConfigAccess.ExtractConfig  = FakeExtractConfig;
   1584   BmmCallbackInfo->FeConfigAccess.RouteConfig    = FileExplorerRouteConfig;
   1585   BmmCallbackInfo->FeConfigAccess.Callback       = FileExplorerCallback;
   1586 
   1587   //
   1588   // Install Device Path Protocol and Config Access protocol to driver handle
   1589   //
   1590   Status = gBS->InstallMultipleProtocolInterfaces (
   1591                   &BmmCallbackInfo->BmmDriverHandle,
   1592                   &gEfiDevicePathProtocolGuid,
   1593                   &mBmmHiiVendorDevicePath,
   1594                   &gEfiHiiConfigAccessProtocolGuid,
   1595                   &BmmCallbackInfo->BmmConfigAccess,
   1596                   NULL
   1597                   );
   1598   ASSERT_EFI_ERROR (Status);
   1599 
   1600   //
   1601   // Install Device Path Protocol and Config Access protocol to driver handle
   1602   //
   1603   Status = gBS->InstallMultipleProtocolInterfaces (
   1604                   &BmmCallbackInfo->FeDriverHandle,
   1605                   &gEfiDevicePathProtocolGuid,
   1606                   &mFeHiiVendorDevicePath,
   1607                   &gEfiHiiConfigAccessProtocolGuid,
   1608                   &BmmCallbackInfo->FeConfigAccess,
   1609                   NULL
   1610                   );
   1611   ASSERT_EFI_ERROR (Status);
   1612 
   1613   //
   1614   // Post our Boot Maint VFR binary to the HII database.
   1615   //
   1616   BmmCallbackInfo->BmmHiiHandle = HiiAddPackages (
   1617                                     &gBootMaintFormSetGuid,
   1618                                     BmmCallbackInfo->BmmDriverHandle,
   1619                                     BmBin,
   1620                                     BdsDxeStrings,
   1621                                     NULL
   1622                                     );
   1623   ASSERT (BmmCallbackInfo->BmmHiiHandle != NULL);
   1624 
   1625   //
   1626   // Post our File Explorer VFR binary to the HII database.
   1627   //
   1628   BmmCallbackInfo->FeHiiHandle = HiiAddPackages (
   1629                                    &gFileExploreFormSetGuid,
   1630                                    BmmCallbackInfo->FeDriverHandle,
   1631                                    FEBin,
   1632                                    BdsDxeStrings,
   1633                                    NULL
   1634                                    );
   1635   ASSERT (BmmCallbackInfo->FeHiiHandle != NULL);
   1636 
   1637   mBmmCallbackInfo = BmmCallbackInfo;
   1638 
   1639   return EFI_SUCCESS;
   1640 }
   1641 
   1642 /**
   1643   Remvoe the intalled BootMaint and FileExplorer HiiPackages.
   1644 
   1645 **/
   1646 VOID
   1647 FreeBMPackage (
   1648   VOID
   1649   )
   1650 {
   1651   BMM_CALLBACK_DATA           *BmmCallbackInfo;
   1652 
   1653   BmmCallbackInfo = mBmmCallbackInfo;
   1654 
   1655   //
   1656   // Remove our IFR data from HII database
   1657   //
   1658   HiiRemovePackages (BmmCallbackInfo->BmmHiiHandle);
   1659   HiiRemovePackages (BmmCallbackInfo->FeHiiHandle);
   1660 
   1661   if (BmmCallbackInfo->FeDriverHandle != NULL) {
   1662     gBS->UninstallMultipleProtocolInterfaces (
   1663            BmmCallbackInfo->FeDriverHandle,
   1664            &gEfiDevicePathProtocolGuid,
   1665            &mFeHiiVendorDevicePath,
   1666            &gEfiHiiConfigAccessProtocolGuid,
   1667            &BmmCallbackInfo->FeConfigAccess,
   1668            NULL
   1669            );
   1670   }
   1671 
   1672   if (BmmCallbackInfo->BmmDriverHandle != NULL) {
   1673     gBS->UninstallMultipleProtocolInterfaces (
   1674            BmmCallbackInfo->BmmDriverHandle,
   1675            &gEfiDevicePathProtocolGuid,
   1676            &mBmmHiiVendorDevicePath,
   1677            &gEfiHiiConfigAccessProtocolGuid,
   1678            &BmmCallbackInfo->BmmConfigAccess,
   1679            NULL
   1680            );
   1681   }
   1682 
   1683   FreePool (BmmCallbackInfo->LoadContext);
   1684   FreePool (BmmCallbackInfo);
   1685 
   1686   mBmmCallbackInfo = NULL;
   1687 
   1688   return;
   1689 }
   1690 
   1691