Home | History | Annotate | Download | only in BootMaint
      1 /** @file
      2 Dynamically update the pages.
      3 
      4 Copyright (c) 2004 - 2016, 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 
     17 /**
     18   Refresh the global UpdateData structure.
     19 
     20 **/
     21 VOID
     22 RefreshUpdateData (
     23   VOID
     24   )
     25 {
     26   //
     27   // Free current updated date
     28   //
     29   if (mStartOpCodeHandle != NULL) {
     30     HiiFreeOpCodeHandle (mStartOpCodeHandle);
     31   }
     32 
     33   //
     34   // Create new OpCode Handle
     35   //
     36   mStartOpCodeHandle = HiiAllocateOpCodeHandle ();
     37 
     38   //
     39   // Create Hii Extend Label OpCode as the start opcode
     40   //
     41   mStartLabel = (EFI_IFR_GUID_LABEL *) HiiCreateGuidOpCode (mStartOpCodeHandle, &gEfiIfrTianoGuid, NULL, sizeof (EFI_IFR_GUID_LABEL));
     42   mStartLabel->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL;
     43 
     44 }
     45 
     46 /**
     47   Add a "Go back to main page" tag in front of the form when there are no
     48   "Apply changes" and "Discard changes" tags in the end of the form.
     49 
     50   @param CallbackData    The BMM context data.
     51 
     52 **/
     53 VOID
     54 UpdatePageStart (
     55   IN BMM_CALLBACK_DATA                *CallbackData
     56   )
     57 {
     58   RefreshUpdateData ();
     59   mStartLabel->Number = CallbackData->BmmCurrentPageId;
     60 
     61   if (!(CallbackData->BmmAskSaveOrNot)) {
     62     //
     63     // Add a "Go back to main page" tag in front of the form when there are no
     64     // "Apply changes" and "Discard changes" tags in the end of the form.
     65     //
     66     HiiCreateGotoOpCode (
     67       mStartOpCodeHandle,
     68       FORM_MAIN_ID,
     69       STRING_TOKEN (STR_FORM_GOTO_MAIN),
     70       STRING_TOKEN (STR_FORM_GOTO_MAIN),
     71       0,
     72       FORM_MAIN_ID
     73       );
     74   }
     75 
     76 }
     77 
     78 /**
     79   Create the "Apply changes" and "Discard changes" tags. And
     80   ensure user can return to the main page.
     81 
     82   @param CallbackData    The BMM context data.
     83 
     84 **/
     85 VOID
     86 UpdatePageEnd (
     87   IN BMM_CALLBACK_DATA                *CallbackData
     88   )
     89 {
     90   //
     91   // Create the "Apply changes" and "Discard changes" tags.
     92   //
     93   if (CallbackData->BmmAskSaveOrNot) {
     94     HiiCreateSubTitleOpCode (
     95       mStartOpCodeHandle,
     96       STRING_TOKEN (STR_NULL_STRING),
     97       0,
     98       0,
     99       0
    100       );
    101 
    102     HiiCreateActionOpCode (
    103       mStartOpCodeHandle,
    104       KEY_VALUE_SAVE_AND_EXIT,
    105       STRING_TOKEN (STR_SAVE_AND_EXIT),
    106       STRING_TOKEN (STR_NULL_STRING),
    107       EFI_IFR_FLAG_CALLBACK,
    108       0
    109       );
    110   }
    111 
    112   //
    113   // Ensure user can return to the main page.
    114   //
    115   HiiCreateActionOpCode (
    116     mStartOpCodeHandle,
    117     KEY_VALUE_NO_SAVE_AND_EXIT,
    118     STRING_TOKEN (STR_NO_SAVE_AND_EXIT),
    119     STRING_TOKEN (STR_NULL_STRING),
    120     EFI_IFR_FLAG_CALLBACK,
    121     0
    122     );
    123 
    124   HiiUpdateForm (
    125     CallbackData->BmmHiiHandle,
    126     &gBootMaintFormSetGuid,
    127     CallbackData->BmmCurrentPageId,
    128     mStartOpCodeHandle, // Label CallbackData->BmmCurrentPageId
    129     mEndOpCodeHandle    // LABEL_END
    130     );
    131 }
    132 
    133 /**
    134   Clean up the dynamic opcode at label and form specified by both LabelId.
    135 
    136   @param LabelId         It is both the Form ID and Label ID for opcode deletion.
    137   @param CallbackData    The BMM context data.
    138 
    139 **/
    140 VOID
    141 CleanUpPage (
    142   IN UINT16                           LabelId,
    143   IN BMM_CALLBACK_DATA                *CallbackData
    144   )
    145 {
    146   RefreshUpdateData ();
    147 
    148   //
    149   // Remove all op-codes from dynamic page
    150   //
    151   mStartLabel->Number = LabelId;
    152   HiiUpdateForm (
    153     CallbackData->BmmHiiHandle,
    154     &gBootMaintFormSetGuid,
    155     LabelId,
    156     mStartOpCodeHandle, // Label LabelId
    157     mEndOpCodeHandle    // LABEL_END
    158     );
    159 }
    160 
    161 /**
    162   Boot a file selected by user at File Expoloer of BMM.
    163 
    164   @param FileContext     The file context data, which contains the device path
    165                          of the file to be boot from.
    166 
    167   @retval EFI_SUCCESS    The function completed successfull.
    168   @return Other value if the boot from the file fails.
    169 
    170 **/
    171 EFI_STATUS
    172 BootThisFile (
    173   IN BM_FILE_CONTEXT                   *FileContext
    174   )
    175 {
    176   EFI_STATUS        Status;
    177   UINTN             ExitDataSize;
    178   CHAR16            *ExitData;
    179   BDS_COMMON_OPTION *Option;
    180 
    181   Option = (BDS_COMMON_OPTION *) AllocatePool (sizeof (BDS_COMMON_OPTION));
    182   ASSERT (Option != NULL);
    183   Option->Description     = (CHAR16 *) AllocateCopyPool (StrSize (FileContext->FileName), FileContext->FileName);
    184   Option->DevicePath      = FileContext->DevicePath;
    185   Option->LoadOptionsSize = 0;
    186   Option->LoadOptions     = NULL;
    187 
    188   //
    189   // Since current no boot from removable media directly is allowed */
    190   //
    191   gST->ConOut->ClearScreen (gST->ConOut);
    192 
    193   ExitDataSize  = 0;
    194 
    195   Status        = BdsLibBootViaBootOption (Option, Option->DevicePath, &ExitDataSize, &ExitData);
    196 
    197   return Status;
    198 
    199 }
    200 
    201 /**
    202   Create a list of Goto Opcode for all terminal devices logged
    203   by TerminaMenu. This list will be inserted to form FORM_CON_COM_SETUP_ID.
    204 
    205   @param CallbackData    The BMM context data.
    206 **/
    207 VOID
    208 UpdateConCOMPage (
    209   IN BMM_CALLBACK_DATA                *CallbackData
    210   )
    211 {
    212   BM_MENU_ENTRY *NewMenuEntry;
    213   UINT16        Index;
    214 
    215   CallbackData->BmmAskSaveOrNot = FALSE;
    216 
    217   UpdatePageStart (CallbackData);
    218 
    219 
    220   for (Index = 0; Index < TerminalMenu.MenuNumber; Index++) {
    221     NewMenuEntry = BOpt_GetMenuEntry (&TerminalMenu, Index);
    222 
    223     HiiCreateGotoOpCode (
    224       mStartOpCodeHandle,
    225       FORM_CON_COM_SETUP_ID,
    226       NewMenuEntry->DisplayStringToken,
    227       STRING_TOKEN (STR_NULL_STRING),
    228       EFI_IFR_FLAG_CALLBACK,
    229       (UINT16) (TERMINAL_OPTION_OFFSET + Index)
    230       );
    231   }
    232 
    233   UpdatePageEnd (CallbackData);
    234 }
    235 
    236 /**
    237   Create a lit of boot option from global BootOptionMenu. It
    238   allow user to delete the boot option.
    239 
    240   @param CallbackData    The BMM context data.
    241 
    242 **/
    243 VOID
    244 UpdateBootDelPage (
    245   IN BMM_CALLBACK_DATA                *CallbackData
    246   )
    247 {
    248   BM_MENU_ENTRY   *NewMenuEntry;
    249   BM_LOAD_CONTEXT *NewLoadContext;
    250   UINT16          Index;
    251 
    252   CallbackData->BmmAskSaveOrNot = TRUE;
    253 
    254   UpdatePageStart (CallbackData);
    255   CreateMenuStringToken (CallbackData, CallbackData->BmmHiiHandle, &BootOptionMenu);
    256 
    257   ASSERT (BootOptionMenu.MenuNumber <= (sizeof (CallbackData->BmmFakeNvData.BootOptionDel) / sizeof (CallbackData->BmmFakeNvData.BootOptionDel[0])));
    258   for (Index = 0; Index < BootOptionMenu.MenuNumber; Index++) {
    259     NewMenuEntry    = BOpt_GetMenuEntry (&BootOptionMenu, Index);
    260     NewLoadContext  = (BM_LOAD_CONTEXT *) NewMenuEntry->VariableContext;
    261     if (NewLoadContext->IsLegacy) {
    262       continue;
    263     }
    264 
    265     NewLoadContext->Deleted = FALSE;
    266 
    267     if (CallbackData->BmmFakeNvData.BootOptionDel[Index] && !CallbackData->BmmFakeNvData.BootOptionDelMark[Index]) {
    268       //
    269       // CallbackData->BmmFakeNvData.BootOptionDel[Index] == TRUE means browser knows this boot option is selected
    270       // CallbackData->BmmFakeNvData.BootOptionDelMark[Index] = FALSE means BDS knows the selected boot option has
    271       // deleted, browser maintains old useless info. So clear this info here, and later update this info to browser
    272       // through HiiSetBrowserData function.
    273       //
    274       CallbackData->BmmFakeNvData.BootOptionDel[Index] = FALSE;
    275     }
    276 
    277     HiiCreateCheckBoxOpCode (
    278       mStartOpCodeHandle,
    279       (EFI_QUESTION_ID) (BOOT_OPTION_DEL_QUESTION_ID + Index),
    280       VARSTORE_ID_BOOT_MAINT,
    281       (UINT16) (BOOT_OPTION_DEL_VAR_OFFSET + Index),
    282       NewMenuEntry->DisplayStringToken,
    283       NewMenuEntry->HelpStringToken,
    284       EFI_IFR_FLAG_CALLBACK,
    285       0,
    286       NULL
    287       );
    288   }
    289 
    290   UpdatePageEnd (CallbackData);
    291 }
    292 
    293 /**
    294   Create a lit of driver option from global DriverMenu.
    295 
    296   @param CallbackData    The BMM context data.
    297 
    298 **/
    299 VOID
    300 UpdateDrvAddHandlePage (
    301   IN BMM_CALLBACK_DATA                *CallbackData
    302   )
    303 {
    304   BM_MENU_ENTRY *NewMenuEntry;
    305   UINT16        Index;
    306 
    307   CallbackData->BmmAskSaveOrNot = FALSE;
    308 
    309   UpdatePageStart (CallbackData);
    310 
    311   for (Index = 0; Index < DriverMenu.MenuNumber; Index++) {
    312     NewMenuEntry = BOpt_GetMenuEntry (&DriverMenu, Index);
    313 
    314     HiiCreateGotoOpCode (
    315       mStartOpCodeHandle,
    316       FORM_DRV_ADD_HANDLE_DESC_ID,
    317       NewMenuEntry->DisplayStringToken,
    318       STRING_TOKEN (STR_NULL_STRING),
    319       EFI_IFR_FLAG_CALLBACK,
    320       (UINT16) (HANDLE_OPTION_OFFSET + Index)
    321       );
    322   }
    323 
    324   UpdatePageEnd (CallbackData);
    325 }
    326 
    327 /**
    328   Create a lit of driver option from global DriverOptionMenu. It
    329   allow user to delete the driver option.
    330 
    331   @param CallbackData    The BMM context data.
    332 
    333 **/
    334 VOID
    335 UpdateDrvDelPage (
    336   IN BMM_CALLBACK_DATA                *CallbackData
    337   )
    338 {
    339   BM_MENU_ENTRY   *NewMenuEntry;
    340   BM_LOAD_CONTEXT *NewLoadContext;
    341   UINT16          Index;
    342 
    343   CallbackData->BmmAskSaveOrNot = TRUE;
    344 
    345   UpdatePageStart (CallbackData);
    346 
    347   CreateMenuStringToken (CallbackData, CallbackData->BmmHiiHandle, &DriverOptionMenu);
    348 
    349   ASSERT (DriverOptionMenu.MenuNumber <= (sizeof (CallbackData->BmmFakeNvData.DriverOptionDel) / sizeof (CallbackData->BmmFakeNvData.DriverOptionDel[0])));
    350   for (Index = 0; Index < DriverOptionMenu.MenuNumber; Index++) {
    351     NewMenuEntry            = BOpt_GetMenuEntry (&DriverOptionMenu, Index);
    352 
    353     NewLoadContext          = (BM_LOAD_CONTEXT *) NewMenuEntry->VariableContext;
    354     NewLoadContext->Deleted = FALSE;
    355 
    356     if (CallbackData->BmmFakeNvData.DriverOptionDel[Index] && !CallbackData->BmmFakeNvData.DriverOptionDelMark[Index]) {
    357       //
    358       // CallbackData->BmmFakeNvData.BootOptionDel[Index] == TRUE means browser knows this boot option is selected
    359       // CallbackData->BmmFakeNvData.BootOptionDelMark[Index] = FALSE means BDS knows the selected boot option has
    360       // deleted, browser maintains old useless info. So clear this info here, and later update this info to browser
    361       // through HiiSetBrowserData function.
    362       //
    363       CallbackData->BmmFakeNvData.DriverOptionDel[Index] = FALSE;
    364     }
    365 
    366     HiiCreateCheckBoxOpCode (
    367       mStartOpCodeHandle,
    368       (EFI_QUESTION_ID) (DRIVER_OPTION_DEL_QUESTION_ID + Index),
    369       VARSTORE_ID_BOOT_MAINT,
    370       (UINT16) (DRIVER_OPTION_DEL_VAR_OFFSET + Index),
    371       NewMenuEntry->DisplayStringToken,
    372       NewMenuEntry->HelpStringToken,
    373       EFI_IFR_FLAG_CALLBACK,
    374       0,
    375       NULL
    376       );
    377   }
    378 
    379   UpdatePageEnd (CallbackData);
    380 }
    381 
    382 /**
    383   Prepare the page to allow user to add description for
    384   a Driver Option.
    385 
    386   @param CallbackData    The BMM context data.
    387 
    388 **/
    389 VOID
    390 UpdateDriverAddHandleDescPage (
    391   IN BMM_CALLBACK_DATA                *CallbackData
    392   )
    393 {
    394   BM_MENU_ENTRY *NewMenuEntry;
    395 
    396   CallbackData->BmmFakeNvData.DriverAddActive          = 0x01;
    397   CallbackData->BmmFakeNvData.DriverAddForceReconnect  = 0x00;
    398   CallbackData->BmmAskSaveOrNot                        = TRUE;
    399   NewMenuEntry = CallbackData->MenuEntry;
    400 
    401   UpdatePageStart (CallbackData);
    402 
    403   HiiCreateSubTitleOpCode (
    404     mStartOpCodeHandle,
    405     NewMenuEntry->DisplayStringToken,
    406     0,
    407     0,
    408     0
    409     );
    410 
    411   HiiCreateStringOpCode (
    412     mStartOpCodeHandle,
    413     (EFI_QUESTION_ID) DRV_ADD_HANDLE_DESC_QUESTION_ID,
    414     VARSTORE_ID_BOOT_MAINT,
    415     DRV_ADD_HANDLE_DESC_VAR_OFFSET,
    416     STRING_TOKEN (STR_LOAD_OPTION_DESC),
    417     STRING_TOKEN (STR_NULL_STRING),
    418     0,
    419     0,
    420     6,
    421     75,
    422     NULL
    423     );
    424 
    425   HiiCreateCheckBoxOpCode (
    426     mStartOpCodeHandle,
    427     (EFI_QUESTION_ID) DRV_ADD_RECON_QUESTION_ID,
    428     VARSTORE_ID_BOOT_MAINT,
    429     DRV_ADD_RECON_VAR_OFFSET,
    430     STRING_TOKEN (STR_LOAD_OPTION_FORCE_RECON),
    431     STRING_TOKEN (STR_LOAD_OPTION_FORCE_RECON),
    432     0,
    433     0,
    434     NULL
    435     );
    436 
    437   HiiCreateStringOpCode (
    438     mStartOpCodeHandle,
    439     (EFI_QUESTION_ID) DRIVER_ADD_OPTION_QUESTION_ID,
    440     VARSTORE_ID_BOOT_MAINT,
    441     DRIVER_ADD_OPTION_VAR_OFFSET,
    442     STRING_TOKEN (STR_OPTIONAL_DATA),
    443     STRING_TOKEN (STR_NULL_STRING),
    444     0,
    445     0,
    446     6,
    447     75,
    448     NULL
    449     );
    450 
    451   UpdatePageEnd (CallbackData);
    452 }
    453 
    454 /**
    455   Update console page.
    456 
    457   @param UpdatePageId    The form ID to be updated.
    458   @param ConsoleMenu     The console menu list.
    459   @param CallbackData    The BMM context data.
    460 
    461 **/
    462 VOID
    463 UpdateConsolePage (
    464   IN UINT16                           UpdatePageId,
    465   IN BM_MENU_OPTION                   *ConsoleMenu,
    466   IN BMM_CALLBACK_DATA                *CallbackData
    467   )
    468 {
    469   BM_MENU_ENTRY       *NewMenuEntry;
    470   UINT16              Index;
    471   UINT8               CheckFlags;
    472   UINT8               *ConsoleCheck;
    473   EFI_QUESTION_ID     QuestionIdBase;
    474   UINT16              VariableOffsetBase;
    475 
    476   UpdatePageStart (CallbackData);
    477 
    478   ConsoleCheck       = NULL;
    479   QuestionIdBase     = 0;
    480   VariableOffsetBase = 0;
    481 
    482   switch (UpdatePageId) {
    483   case FORM_CON_IN_ID:
    484     ConsoleCheck       = &CallbackData->BmmFakeNvData.ConsoleInCheck[0];
    485     QuestionIdBase     = CON_IN_DEVICE_QUESTION_ID;
    486     VariableOffsetBase = CON_IN_DEVICE_VAR_OFFSET;
    487     break;
    488 
    489   case FORM_CON_OUT_ID:
    490     ConsoleCheck       = &CallbackData->BmmFakeNvData.ConsoleOutCheck[0];
    491     QuestionIdBase     = CON_OUT_DEVICE_QUESTION_ID;
    492     VariableOffsetBase = CON_OUT_DEVICE_VAR_OFFSET;
    493     break;
    494 
    495   case FORM_CON_ERR_ID:
    496     ConsoleCheck       = &CallbackData->BmmFakeNvData.ConsoleErrCheck[0];
    497     QuestionIdBase     = CON_ERR_DEVICE_QUESTION_ID;
    498     VariableOffsetBase = CON_ERR_DEVICE_VAR_OFFSET;
    499     break;
    500   }
    501   ASSERT (ConsoleCheck != NULL);
    502 
    503   for (Index = 0; ((Index < ConsoleMenu->MenuNumber) && \
    504        (Index < MAX_MENU_NUMBER)) ; Index++) {
    505     CheckFlags = 0;
    506     if (UpdatePageId != FORM_CON_ERR_ID) {
    507       CheckFlags |= EFI_IFR_CHECKBOX_DEFAULT;
    508     }
    509     NewMenuEntry = BOpt_GetMenuEntry (ConsoleMenu, Index);
    510     HiiCreateCheckBoxOpCode (
    511       mStartOpCodeHandle,
    512       (EFI_QUESTION_ID) (QuestionIdBase + Index),
    513       VARSTORE_ID_BOOT_MAINT,
    514       (UINT16) (VariableOffsetBase + Index),
    515       NewMenuEntry->DisplayStringToken,
    516       NewMenuEntry->HelpStringToken,
    517       0,
    518       CheckFlags,
    519       NULL
    520       );
    521   }
    522 
    523   UpdatePageEnd (CallbackData);
    524 }
    525 
    526 /**
    527   Update the page's NV Map if user has changed the order
    528   a list. This list can be Boot Order or Driver Order.
    529 
    530   @param UpdatePageId    The form ID to be updated.
    531   @param OptionMenu      The new list.
    532   @param CallbackData    The BMM context data.
    533 
    534 **/
    535 VOID
    536 UpdateOrderPage (
    537   IN UINT16                           UpdatePageId,
    538   IN BM_MENU_OPTION                   *OptionMenu,
    539   IN BMM_CALLBACK_DATA                *CallbackData
    540   )
    541 {
    542   BM_MENU_ENTRY     *NewMenuEntry;
    543   UINT16            Index;
    544   UINT16            OptionIndex;
    545   VOID              *OptionsOpCodeHandle;
    546   BOOLEAN           BootOptionFound;
    547   UINT32            *OptionOrder;
    548   EFI_QUESTION_ID   QuestionId;
    549   UINT16            VarOffset;
    550 
    551 
    552   UpdatePageStart (CallbackData);
    553 
    554   CreateMenuStringToken (CallbackData, CallbackData->BmmHiiHandle, OptionMenu);
    555 
    556   OptionOrder = NULL;
    557   QuestionId = 0;
    558   VarOffset = 0;
    559   switch (UpdatePageId) {
    560 
    561   case FORM_BOOT_CHG_ID:
    562     //
    563     // If the BootOptionOrder in the BmmFakeNvData are same with the date in the BmmOldFakeNVData,
    564     // means all Boot Options has been save in BootOptionMenu, we can get the date from the menu.
    565     // else means browser maintains some uncommitted date which are not saved in BootOptionMenu,
    566     // so we should not get the data from BootOptionMenu to show it.
    567     //
    568     if (CompareMem (CallbackData->BmmFakeNvData.BootOptionOrder, CallbackData->BmmOldFakeNVData.BootOptionOrder, sizeof (CallbackData->BmmFakeNvData.BootOptionOrder)) == 0) {
    569       GetBootOrder (CallbackData);
    570     }
    571     OptionOrder = CallbackData->BmmFakeNvData.BootOptionOrder;
    572     QuestionId = BOOT_OPTION_ORDER_QUESTION_ID;
    573     VarOffset = BOOT_OPTION_ORDER_VAR_OFFSET;
    574     break;
    575 
    576   case FORM_DRV_CHG_ID:
    577     //
    578     // If the DriverOptionOrder in the BmmFakeNvData are same with the date in the BmmOldFakeNVData,
    579     // means all Driver Options has been save in DriverOptionMenu, we can get the DriverOptionOrder from the menu.
    580     // else means browser maintains some uncommitted date which are not saved in DriverOptionMenu,
    581     // so we should not get the data from DriverOptionMenu to show it.
    582     //
    583     if (CompareMem (CallbackData->BmmFakeNvData.DriverOptionOrder, CallbackData->BmmOldFakeNVData.DriverOptionOrder, sizeof (CallbackData->BmmFakeNvData.DriverOptionOrder)) == 0) {
    584       GetDriverOrder (CallbackData);
    585     }
    586     OptionOrder = CallbackData->BmmFakeNvData.DriverOptionOrder;
    587     QuestionId = DRIVER_OPTION_ORDER_QUESTION_ID;
    588     VarOffset = DRIVER_OPTION_ORDER_VAR_OFFSET;
    589     break;
    590   }
    591   ASSERT (OptionOrder != NULL);
    592 
    593   OptionsOpCodeHandle = HiiAllocateOpCodeHandle ();
    594   ASSERT (OptionsOpCodeHandle != NULL);
    595 
    596   NewMenuEntry = NULL;
    597   for (OptionIndex = 0; (OptionIndex < MAX_MENU_NUMBER && OptionOrder[OptionIndex] != 0); OptionIndex++) {
    598     BootOptionFound = FALSE;
    599     for (Index = 0; Index < OptionMenu->MenuNumber; Index++) {
    600       NewMenuEntry   = BOpt_GetMenuEntry (OptionMenu, Index);
    601       if ((UINT32) (NewMenuEntry->OptionNumber + 1) == OptionOrder[OptionIndex]) {
    602         BootOptionFound = TRUE;
    603         break;
    604       }
    605     }
    606     if (BootOptionFound) {
    607       HiiCreateOneOfOptionOpCode (
    608         OptionsOpCodeHandle,
    609         NewMenuEntry->DisplayStringToken,
    610         0,
    611         EFI_IFR_TYPE_NUM_SIZE_32,
    612         OptionOrder[OptionIndex]
    613         );
    614     }
    615   }
    616 
    617   if (OptionMenu->MenuNumber > 0) {
    618     HiiCreateOrderedListOpCode (
    619       mStartOpCodeHandle,                          // Container for dynamic created opcodes
    620       QuestionId,                                  // Question ID
    621       VARSTORE_ID_BOOT_MAINT,                      // VarStore ID
    622       VarOffset,                                   // Offset in Buffer Storage
    623       STRING_TOKEN (STR_CHANGE_ORDER),             // Question prompt text
    624       STRING_TOKEN (STR_CHANGE_ORDER),             // Question help text
    625       0,                                           // Question flag
    626       0,                                           // Ordered list flag, e.g. EFI_IFR_UNIQUE_SET
    627       EFI_IFR_TYPE_NUM_SIZE_32,                    // Data type of Question value
    628       100,                                         // Maximum container
    629       OptionsOpCodeHandle,                         // Option Opcode list
    630       NULL                                         // Default Opcode is NULL
    631       );
    632   }
    633 
    634   HiiFreeOpCodeHandle (OptionsOpCodeHandle);
    635 
    636   UpdatePageEnd (CallbackData);
    637 }
    638 
    639 /**
    640   Create the dynamic page to allow user to set
    641   the "BootNext" value.
    642 
    643   @param CallbackData    The BMM context data.
    644 
    645 **/
    646 VOID
    647 UpdateBootNextPage (
    648   IN BMM_CALLBACK_DATA                *CallbackData
    649   )
    650 {
    651   BM_MENU_ENTRY   *NewMenuEntry;
    652   BM_LOAD_CONTEXT *NewLoadContext;
    653   UINTN           NumberOfOptions;
    654   UINT16          Index;
    655   VOID            *OptionsOpCodeHandle;
    656 
    657   NumberOfOptions               = BootOptionMenu.MenuNumber;
    658   CallbackData->BmmAskSaveOrNot = TRUE;
    659 
    660   UpdatePageStart (CallbackData);
    661   CreateMenuStringToken (CallbackData, CallbackData->BmmHiiHandle, &BootOptionMenu);
    662 
    663   if (NumberOfOptions > 0) {
    664     OptionsOpCodeHandle = HiiAllocateOpCodeHandle ();
    665     ASSERT (OptionsOpCodeHandle != NULL);
    666 
    667     //CallbackData->BmmFakeNvData.BootNext = (UINT16) (BootOptionMenu.MenuNumber);
    668 
    669     for (Index = 0; Index < BootOptionMenu.MenuNumber; Index++) {
    670       NewMenuEntry    = BOpt_GetMenuEntry (&BootOptionMenu, Index);
    671       NewLoadContext  = (BM_LOAD_CONTEXT *) NewMenuEntry->VariableContext;
    672 
    673       if (NewLoadContext->IsBootNext) {
    674         HiiCreateOneOfOptionOpCode (
    675           OptionsOpCodeHandle,
    676           NewMenuEntry->DisplayStringToken,
    677           EFI_IFR_OPTION_DEFAULT,
    678           EFI_IFR_TYPE_NUM_SIZE_16,
    679           Index
    680           );
    681         //CallbackData->BmmFakeNvData.BootNext = Index;
    682       } else {
    683         HiiCreateOneOfOptionOpCode (
    684           OptionsOpCodeHandle,
    685           NewMenuEntry->DisplayStringToken,
    686           0,
    687           EFI_IFR_TYPE_NUM_SIZE_16,
    688           Index
    689           );
    690       }
    691     }
    692 
    693     if (CallbackData->BmmFakeNvData.BootNext == Index) {
    694       HiiCreateOneOfOptionOpCode (
    695         OptionsOpCodeHandle,
    696         STRING_TOKEN (STR_NONE),
    697         EFI_IFR_OPTION_DEFAULT,
    698         EFI_IFR_TYPE_NUM_SIZE_16,
    699         Index
    700         );
    701     } else {
    702       HiiCreateOneOfOptionOpCode (
    703         OptionsOpCodeHandle,
    704         STRING_TOKEN (STR_NONE),
    705         0,
    706         EFI_IFR_TYPE_NUM_SIZE_16,
    707         Index
    708         );
    709     }
    710 
    711     HiiCreateOneOfOpCode (
    712       mStartOpCodeHandle,
    713       (EFI_QUESTION_ID) BOOT_NEXT_QUESTION_ID,
    714       VARSTORE_ID_BOOT_MAINT,
    715       BOOT_NEXT_VAR_OFFSET,
    716       STRING_TOKEN (STR_BOOT_NEXT),
    717       STRING_TOKEN (STR_BOOT_NEXT_HELP),
    718       0,
    719       EFI_IFR_NUMERIC_SIZE_2,
    720       OptionsOpCodeHandle,
    721       NULL
    722       );
    723 
    724     HiiFreeOpCodeHandle (OptionsOpCodeHandle);
    725   }
    726 
    727   UpdatePageEnd (CallbackData);
    728 }
    729 
    730 /**
    731   Create the dynamic page to allow user to set the "TimeOut" value.
    732 
    733   @param CallbackData    The BMM context data.
    734 
    735 **/
    736 VOID
    737 UpdateTimeOutPage (
    738   IN BMM_CALLBACK_DATA                *CallbackData
    739   )
    740 {
    741   UINT16  BootTimeOut;
    742   VOID    *DefaultOpCodeHandle;
    743 
    744   CallbackData->BmmAskSaveOrNot = TRUE;
    745 
    746   UpdatePageStart (CallbackData);
    747 
    748   BootTimeOut = PcdGet16 (PcdPlatformBootTimeOut);
    749 
    750   DefaultOpCodeHandle = HiiAllocateOpCodeHandle ();
    751   ASSERT (DefaultOpCodeHandle != NULL);
    752   HiiCreateDefaultOpCode (DefaultOpCodeHandle, EFI_HII_DEFAULT_CLASS_STANDARD, EFI_IFR_TYPE_NUM_SIZE_16, BootTimeOut);
    753 
    754   HiiCreateNumericOpCode (
    755     mStartOpCodeHandle,
    756     (EFI_QUESTION_ID) BOOT_TIME_OUT_QUESTION_ID,
    757     VARSTORE_ID_BOOT_MAINT,
    758     BOOT_TIME_OUT_VAR_OFFSET,
    759     STRING_TOKEN (STR_NUM_AUTO_BOOT),
    760     STRING_TOKEN (STR_HLP_AUTO_BOOT),
    761     0,
    762     EFI_IFR_NUMERIC_SIZE_2 | EFI_IFR_DISPLAY_UINT_DEC,
    763     0,
    764     65535,
    765     0,
    766     DefaultOpCodeHandle
    767     );
    768 
    769   HiiFreeOpCodeHandle (DefaultOpCodeHandle);
    770 
    771   //CallbackData->BmmFakeNvData.BootTimeOut = BootTimeOut;
    772 
    773   UpdatePageEnd (CallbackData);
    774 }
    775 
    776 /**
    777   Refresh the text mode page.
    778 
    779   @param CallbackData    The BMM context data.
    780 
    781 **/
    782 VOID
    783 UpdateConModePage (
    784   IN BMM_CALLBACK_DATA                *CallbackData
    785   )
    786 {
    787   UINTN                         Mode;
    788   UINTN                         Index;
    789   UINTN                         Col;
    790   UINTN                         Row;
    791   CHAR16                        ModeString[50];
    792   CHAR16                        *PStr;
    793   UINTN                         MaxMode;
    794   UINTN                         ValidMode;
    795   EFI_STRING_ID                 *ModeToken;
    796   EFI_STATUS                    Status;
    797   VOID                          *OptionsOpCodeHandle;
    798   EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL  *ConOut;
    799 
    800   ConOut    = gST->ConOut;
    801   Index     = 0;
    802   ValidMode = 0;
    803   MaxMode   = (UINTN) (ConOut->Mode->MaxMode);
    804 
    805   CallbackData->BmmAskSaveOrNot = TRUE;
    806 
    807   UpdatePageStart (CallbackData);
    808 
    809   //
    810   // Check valid mode
    811   //
    812   for (Mode = 0; Mode < MaxMode; Mode++) {
    813     Status = ConOut->QueryMode (ConOut, Mode, &Col, &Row);
    814     if (EFI_ERROR (Status)) {
    815       continue;
    816     }
    817     ValidMode++;
    818   }
    819 
    820   if (ValidMode == 0) {
    821     return;
    822   }
    823 
    824   OptionsOpCodeHandle = HiiAllocateOpCodeHandle ();
    825   ASSERT (OptionsOpCodeHandle != NULL);
    826 
    827   ModeToken           = AllocateZeroPool (sizeof (EFI_STRING_ID) * ValidMode);
    828   ASSERT(ModeToken != NULL);
    829 
    830   //
    831   // Determin which mode should be the first entry in menu
    832   //
    833   // GetConsoleOutMode (CallbackData);
    834 
    835   //
    836   // Build text mode options
    837   //
    838   for (Mode = 0; Mode < MaxMode; Mode++) {
    839     Status = ConOut->QueryMode (ConOut, Mode, &Col, &Row);
    840     if (EFI_ERROR (Status)) {
    841       continue;
    842     }
    843 
    844     //
    845     // Build mode string Column x Row
    846     //
    847     UnicodeValueToString (ModeString, 0, Col, 0);
    848     PStr = &ModeString[0];
    849     StrCatS (PStr, ARRAY_SIZE (ModeString), L" x ");
    850     PStr = PStr + StrLen (PStr);
    851     UnicodeValueToString (PStr , 0, Row, 0);
    852 
    853     ModeToken[Index] = HiiSetString (CallbackData->BmmHiiHandle, 0, ModeString, NULL);
    854 
    855     if (Mode == CallbackData->BmmFakeNvData.ConsoleOutMode) {
    856       HiiCreateOneOfOptionOpCode (
    857         OptionsOpCodeHandle,
    858         ModeToken[Index],
    859         EFI_IFR_OPTION_DEFAULT,
    860         EFI_IFR_TYPE_NUM_SIZE_16,
    861         (UINT16) Mode
    862         );
    863     } else {
    864       HiiCreateOneOfOptionOpCode (
    865         OptionsOpCodeHandle,
    866         ModeToken[Index],
    867         0,
    868         EFI_IFR_TYPE_NUM_SIZE_16,
    869         (UINT16) Mode
    870         );
    871     }
    872     Index++;
    873   }
    874 
    875   HiiCreateOneOfOpCode (
    876     mStartOpCodeHandle,
    877     (EFI_QUESTION_ID) CON_MODE_QUESTION_ID,
    878     VARSTORE_ID_BOOT_MAINT,
    879     CON_MODE_VAR_OFFSET,
    880     STRING_TOKEN (STR_CON_MODE_SETUP),
    881     STRING_TOKEN (STR_CON_MODE_SETUP),
    882     EFI_IFR_FLAG_RESET_REQUIRED,
    883     EFI_IFR_NUMERIC_SIZE_2,
    884     OptionsOpCodeHandle,
    885     NULL
    886     );
    887 
    888   HiiFreeOpCodeHandle (OptionsOpCodeHandle);
    889   FreePool (ModeToken);
    890 
    891   UpdatePageEnd (CallbackData);
    892 }
    893 
    894 /**
    895   Create the dynamic page which allows user to set the property such as Baud Rate, Data Bits,
    896   Parity, Stop Bits, Terminal Type.
    897 
    898   @param CallbackData    The BMM context data.
    899 
    900 **/
    901 VOID
    902 UpdateTerminalPage (
    903   IN BMM_CALLBACK_DATA                *CallbackData
    904   )
    905 {
    906   UINT8               Index;
    907   UINT8               CheckFlags;
    908   BM_MENU_ENTRY       *NewMenuEntry;
    909   VOID                *OptionsOpCodeHandle;
    910   UINTN               CurrentTerminal;
    911 
    912   UpdatePageStart (CallbackData);
    913 
    914   CurrentTerminal = CallbackData->CurrentTerminal;
    915   NewMenuEntry = BOpt_GetMenuEntry (
    916                   &TerminalMenu,
    917                   CurrentTerminal
    918                   );
    919 
    920   if (NewMenuEntry == NULL) {
    921     return ;
    922   }
    923 
    924   OptionsOpCodeHandle = HiiAllocateOpCodeHandle ();
    925   ASSERT (OptionsOpCodeHandle != NULL);
    926 
    927   for (Index = 0; Index < sizeof (BaudRateList) / sizeof (BaudRateList [0]); Index++) {
    928     CheckFlags = 0;
    929     if (BaudRateList[Index].Value == 115200) {
    930       CheckFlags |= EFI_IFR_OPTION_DEFAULT;
    931     }
    932     HiiCreateOneOfOptionOpCode (
    933       OptionsOpCodeHandle,
    934       BaudRateList[Index].StringToken,
    935       CheckFlags,
    936       EFI_IFR_TYPE_NUM_SIZE_8,
    937       Index
    938       );
    939   }
    940 
    941   HiiCreateOneOfOpCode (
    942     mStartOpCodeHandle,
    943     (EFI_QUESTION_ID) (COM_BAUD_RATE_QUESTION_ID + CurrentTerminal),
    944     VARSTORE_ID_BOOT_MAINT,
    945     (UINT16) (COM_BAUD_RATE_VAR_OFFSET + CurrentTerminal),
    946     STRING_TOKEN (STR_COM_BAUD_RATE),
    947     STRING_TOKEN (STR_COM_BAUD_RATE),
    948     0,
    949     EFI_IFR_NUMERIC_SIZE_1,
    950     OptionsOpCodeHandle,
    951     NULL
    952     );
    953 
    954   HiiFreeOpCodeHandle (OptionsOpCodeHandle);
    955   OptionsOpCodeHandle = HiiAllocateOpCodeHandle ();
    956   ASSERT (OptionsOpCodeHandle != NULL);
    957 
    958   for (Index = 0; Index < ARRAY_SIZE (DataBitsList); Index++) {
    959     CheckFlags = 0;
    960 
    961     if (DataBitsList[Index].Value == 8) {
    962       CheckFlags |= EFI_IFR_OPTION_DEFAULT;
    963     }
    964 
    965     HiiCreateOneOfOptionOpCode (
    966       OptionsOpCodeHandle,
    967       DataBitsList[Index].StringToken,
    968       CheckFlags,
    969       EFI_IFR_TYPE_NUM_SIZE_8,
    970       Index
    971       );
    972   }
    973 
    974   HiiCreateOneOfOpCode (
    975     mStartOpCodeHandle,
    976     (EFI_QUESTION_ID) (COM_DATA_RATE_QUESTION_ID + CurrentTerminal),
    977     VARSTORE_ID_BOOT_MAINT,
    978     (UINT16) (COM_DATA_RATE_VAR_OFFSET + CurrentTerminal),
    979     STRING_TOKEN (STR_COM_DATA_BITS),
    980     STRING_TOKEN (STR_COM_DATA_BITS),
    981     0,
    982     EFI_IFR_NUMERIC_SIZE_1,
    983     OptionsOpCodeHandle,
    984     NULL
    985     );
    986 
    987   HiiFreeOpCodeHandle (OptionsOpCodeHandle);
    988   OptionsOpCodeHandle = HiiAllocateOpCodeHandle ();
    989   ASSERT (OptionsOpCodeHandle != NULL);
    990 
    991   for (Index = 0; Index < ARRAY_SIZE (ParityList); Index++) {
    992     CheckFlags = 0;
    993     if (ParityList[Index].Value ==  NoParity) {
    994       CheckFlags |= EFI_IFR_OPTION_DEFAULT;
    995     }
    996 
    997     HiiCreateOneOfOptionOpCode (
    998       OptionsOpCodeHandle,
    999       ParityList[Index].StringToken,
   1000       CheckFlags,
   1001       EFI_IFR_TYPE_NUM_SIZE_8,
   1002       Index
   1003       );
   1004   }
   1005 
   1006   HiiCreateOneOfOpCode (
   1007     mStartOpCodeHandle,
   1008     (EFI_QUESTION_ID) (COM_PARITY_QUESTION_ID + CurrentTerminal),
   1009     VARSTORE_ID_BOOT_MAINT,
   1010     (UINT16) (COM_PARITY_VAR_OFFSET + CurrentTerminal),
   1011     STRING_TOKEN (STR_COM_PARITY),
   1012     STRING_TOKEN (STR_COM_PARITY),
   1013     0,
   1014     EFI_IFR_NUMERIC_SIZE_1,
   1015     OptionsOpCodeHandle,
   1016     NULL
   1017     );
   1018 
   1019   HiiFreeOpCodeHandle (OptionsOpCodeHandle);
   1020   OptionsOpCodeHandle = HiiAllocateOpCodeHandle ();
   1021   ASSERT (OptionsOpCodeHandle != NULL);
   1022 
   1023   for (Index = 0; Index < ARRAY_SIZE (StopBitsList); Index++) {
   1024     CheckFlags = 0;
   1025     if (StopBitsList[Index].Value == OneStopBit) {
   1026       CheckFlags |= EFI_IFR_OPTION_DEFAULT;
   1027     }
   1028 
   1029     HiiCreateOneOfOptionOpCode (
   1030       OptionsOpCodeHandle,
   1031       StopBitsList[Index].StringToken,
   1032       CheckFlags,
   1033       EFI_IFR_TYPE_NUM_SIZE_8,
   1034       Index
   1035       );
   1036   }
   1037 
   1038   HiiCreateOneOfOpCode (
   1039     mStartOpCodeHandle,
   1040     (EFI_QUESTION_ID) (COM_STOP_BITS_QUESTION_ID + CurrentTerminal),
   1041     VARSTORE_ID_BOOT_MAINT,
   1042     (UINT16) (COM_STOP_BITS_VAR_OFFSET + CurrentTerminal),
   1043     STRING_TOKEN (STR_COM_STOP_BITS),
   1044     STRING_TOKEN (STR_COM_STOP_BITS),
   1045     0,
   1046     EFI_IFR_NUMERIC_SIZE_1,
   1047     OptionsOpCodeHandle,
   1048     NULL
   1049     );
   1050 
   1051   HiiFreeOpCodeHandle (OptionsOpCodeHandle);
   1052   OptionsOpCodeHandle = HiiAllocateOpCodeHandle ();
   1053   ASSERT (OptionsOpCodeHandle != NULL);
   1054 
   1055   for (Index = 0; Index < 4; Index++) {
   1056     CheckFlags = 0;
   1057     if (Index == 0) {
   1058       CheckFlags |= EFI_IFR_OPTION_DEFAULT;
   1059     }
   1060 
   1061     HiiCreateOneOfOptionOpCode (
   1062       OptionsOpCodeHandle,
   1063       (EFI_STRING_ID) TerminalType[Index],
   1064       CheckFlags,
   1065       EFI_IFR_TYPE_NUM_SIZE_8,
   1066       Index
   1067       );
   1068   }
   1069 
   1070   HiiCreateOneOfOpCode (
   1071     mStartOpCodeHandle,
   1072     (EFI_QUESTION_ID) (COM_TERMINAL_QUESTION_ID + CurrentTerminal),
   1073     VARSTORE_ID_BOOT_MAINT,
   1074     (UINT16) (COM_TERMINAL_VAR_OFFSET + CurrentTerminal),
   1075     STRING_TOKEN (STR_COM_TERMI_TYPE),
   1076     STRING_TOKEN (STR_COM_TERMI_TYPE),
   1077     0,
   1078     EFI_IFR_NUMERIC_SIZE_1,
   1079     OptionsOpCodeHandle,
   1080     NULL
   1081     );
   1082 
   1083   HiiFreeOpCodeHandle (OptionsOpCodeHandle);
   1084   OptionsOpCodeHandle = HiiAllocateOpCodeHandle ();
   1085   ASSERT (OptionsOpCodeHandle != NULL);
   1086 
   1087   for (Index = 0; Index < ARRAY_SIZE (mFlowControlType); Index++) {
   1088   CheckFlags = 0;
   1089     if (Index == 0) {
   1090       CheckFlags |= EFI_IFR_OPTION_DEFAULT;
   1091     }
   1092     HiiCreateOneOfOptionOpCode (
   1093       OptionsOpCodeHandle,
   1094       (EFI_STRING_ID) mFlowControlType[Index],
   1095       CheckFlags,
   1096       EFI_IFR_TYPE_NUM_SIZE_8,
   1097       mFlowControlValue[Index]
   1098       );
   1099   }
   1100 
   1101   HiiCreateOneOfOpCode (
   1102     mStartOpCodeHandle,
   1103     (EFI_QUESTION_ID) (COM_FLOWCONTROL_QUESTION_ID + CurrentTerminal),
   1104     VARSTORE_ID_BOOT_MAINT,
   1105     (UINT16) (COM_FLOWCONTROL_VAR_OFFSET + CurrentTerminal),
   1106     STRING_TOKEN (STR_COM_FLOW_CONTROL),
   1107     STRING_TOKEN (STR_COM_FLOW_CONTROL),
   1108     0,
   1109     EFI_IFR_NUMERIC_SIZE_1,
   1110     OptionsOpCodeHandle,
   1111     NULL
   1112     );
   1113 
   1114   HiiFreeOpCodeHandle (OptionsOpCodeHandle);
   1115 
   1116   UpdatePageEnd (CallbackData);
   1117 }
   1118 
   1119 /**
   1120   Dispatch the correct update page function to call based on
   1121   the UpdatePageId.
   1122 
   1123   @param UpdatePageId    The form ID.
   1124   @param CallbackData    The BMM context data.
   1125 
   1126 **/
   1127 VOID
   1128 UpdatePageBody (
   1129   IN UINT16                           UpdatePageId,
   1130   IN BMM_CALLBACK_DATA                *CallbackData
   1131   )
   1132 {
   1133   CleanUpPage (UpdatePageId, CallbackData);
   1134   switch (UpdatePageId) {
   1135   case FORM_CON_IN_ID:
   1136     UpdateConsolePage (UpdatePageId, &ConsoleInpMenu, CallbackData);
   1137     break;
   1138 
   1139   case FORM_CON_OUT_ID:
   1140     UpdateConsolePage (UpdatePageId, &ConsoleOutMenu, CallbackData);
   1141     break;
   1142 
   1143   case FORM_CON_ERR_ID:
   1144     UpdateConsolePage (UpdatePageId, &ConsoleErrMenu, CallbackData);
   1145     break;
   1146 
   1147   case FORM_BOOT_CHG_ID:
   1148     UpdateOrderPage (UpdatePageId, &BootOptionMenu, CallbackData);
   1149     break;
   1150 
   1151   case FORM_DRV_CHG_ID:
   1152     UpdateOrderPage (UpdatePageId, &DriverOptionMenu, CallbackData);
   1153     break;
   1154 
   1155   default:
   1156     break;
   1157   }
   1158 }
   1159 
   1160 /**
   1161   Create a dynamic page so that Legacy Device boot order
   1162   can be set for specified device type.
   1163 
   1164   @param UpdatePageId    The form ID. It also spefies the legacy device type.
   1165   @param CallbackData    The BMM context data.
   1166 
   1167 
   1168 **/
   1169 VOID
   1170 UpdateSetLegacyDeviceOrderPage (
   1171   IN UINT16                           UpdatePageId,
   1172   IN BMM_CALLBACK_DATA                *CallbackData
   1173   )
   1174 {
   1175   LEGACY_DEV_ORDER_ENTRY      *DevOrder;
   1176   BM_MENU_OPTION              *OptionMenu;
   1177   BM_MENU_ENTRY               *NewMenuEntry;
   1178   EFI_STRING_ID               StrRef;
   1179   EFI_STRING_ID               StrRefHelp;
   1180   BBS_TYPE                    BbsType;
   1181   UINTN                       VarSize;
   1182   UINTN                       Pos;
   1183   UINTN                       Bit;
   1184   UINT16                      Index;
   1185   UINT16                      Key;
   1186   CHAR16                      String[100];
   1187   CHAR16                      *TypeStr;
   1188   CHAR16                      *TypeStrHelp;
   1189   UINT16                      VarDevOrder;
   1190   UINT8                       *VarData;
   1191   UINT8                       *LegacyOrder;
   1192   UINT8                       *OldData;
   1193   UINT8                       *DisMap;
   1194   VOID                        *OptionsOpCodeHandle;
   1195 
   1196   OptionMenu = NULL;
   1197   Key = 0;
   1198   StrRef = 0;
   1199   StrRefHelp = 0;
   1200   TypeStr = NULL;
   1201   TypeStrHelp = NULL;
   1202   BbsType = BBS_FLOPPY;
   1203   LegacyOrder = NULL;
   1204   OldData = NULL;
   1205   DisMap = NULL;
   1206 
   1207   CallbackData->BmmAskSaveOrNot = TRUE;
   1208   UpdatePageStart (CallbackData);
   1209 
   1210   DisMap = ZeroMem (CallbackData->BmmOldFakeNVData.DisableMap, sizeof (CallbackData->BmmOldFakeNVData.DisableMap));
   1211 
   1212   //
   1213   // Create oneof option list
   1214   //
   1215   switch (UpdatePageId) {
   1216   case FORM_SET_FD_ORDER_ID:
   1217     OptionMenu  = (BM_MENU_OPTION *) &LegacyFDMenu;
   1218     Key         = (UINT16) LEGACY_FD_QUESTION_ID;
   1219     TypeStr     = STR_FLOPPY;
   1220     TypeStrHelp = STR_FLOPPY_HELP;
   1221     BbsType     = BBS_FLOPPY;
   1222     LegacyOrder = CallbackData->BmmFakeNvData.LegacyFD;
   1223     OldData     = CallbackData->BmmOldFakeNVData.LegacyFD;
   1224     break;
   1225 
   1226   case FORM_SET_HD_ORDER_ID:
   1227     OptionMenu  = (BM_MENU_OPTION *) &LegacyHDMenu;
   1228     Key         = (UINT16) LEGACY_HD_QUESTION_ID;
   1229     TypeStr     = STR_HARDDISK;
   1230     TypeStrHelp = STR_HARDDISK_HELP;
   1231     BbsType     = BBS_HARDDISK;
   1232     LegacyOrder = CallbackData->BmmFakeNvData.LegacyHD;
   1233     OldData     = CallbackData->BmmOldFakeNVData.LegacyHD;
   1234     break;
   1235 
   1236   case FORM_SET_CD_ORDER_ID:
   1237     OptionMenu  = (BM_MENU_OPTION *) &LegacyCDMenu;
   1238     Key         = (UINT16) LEGACY_CD_QUESTION_ID;
   1239     TypeStr     = STR_CDROM;
   1240     TypeStrHelp = STR_CDROM_HELP;
   1241     BbsType     = BBS_CDROM;
   1242     LegacyOrder = CallbackData->BmmFakeNvData.LegacyCD;
   1243     OldData     = CallbackData->BmmOldFakeNVData.LegacyCD;
   1244     break;
   1245 
   1246   case FORM_SET_NET_ORDER_ID:
   1247     OptionMenu  = (BM_MENU_OPTION *) &LegacyNETMenu;
   1248     Key         = (UINT16) LEGACY_NET_QUESTION_ID;
   1249     TypeStr     = STR_NET;
   1250     TypeStrHelp = STR_NET_HELP;
   1251     BbsType     = BBS_EMBED_NETWORK;
   1252     LegacyOrder = CallbackData->BmmFakeNvData.LegacyNET;
   1253     OldData     = CallbackData->BmmOldFakeNVData.LegacyNET;
   1254     break;
   1255 
   1256   case FORM_SET_BEV_ORDER_ID:
   1257     OptionMenu  = (BM_MENU_OPTION *) &LegacyBEVMenu;
   1258     Key         = (UINT16) LEGACY_BEV_QUESTION_ID;
   1259     TypeStr     = STR_BEV;
   1260     TypeStrHelp = STR_BEV_HELP;
   1261     BbsType     = BBS_BEV_DEVICE;
   1262     LegacyOrder = CallbackData->BmmFakeNvData.LegacyBEV;
   1263     OldData     = CallbackData->BmmOldFakeNVData.LegacyBEV;
   1264     break;
   1265 
   1266   default:
   1267     DEBUG ((EFI_D_ERROR, "Invalid command ID for updating page!\n"));
   1268     return;
   1269   }
   1270 
   1271   CreateMenuStringToken (CallbackData, CallbackData->BmmHiiHandle, OptionMenu);
   1272 
   1273   OptionsOpCodeHandle = HiiAllocateOpCodeHandle ();
   1274   ASSERT (OptionsOpCodeHandle != NULL);
   1275 
   1276   for (Index = 0; Index < OptionMenu->MenuNumber; Index++) {
   1277     NewMenuEntry                = BOpt_GetMenuEntry (OptionMenu, Index);
   1278     //
   1279     // Create OneOf for each legacy device
   1280     //
   1281     HiiCreateOneOfOptionOpCode (
   1282       OptionsOpCodeHandle,
   1283       NewMenuEntry->DisplayStringToken,
   1284       0,
   1285       EFI_IFR_TYPE_NUM_SIZE_8,
   1286       (UINT8) ((BM_LEGACY_DEVICE_CONTEXT *) NewMenuEntry->VariableContext)->BbsIndex
   1287       );
   1288   }
   1289 
   1290   //
   1291   // Create OneOf for item "Disabled"
   1292   //
   1293   HiiCreateOneOfOptionOpCode (
   1294     OptionsOpCodeHandle,
   1295     STRING_TOKEN (STR_DISABLE_LEGACY_DEVICE),
   1296     0,
   1297     EFI_IFR_TYPE_NUM_SIZE_8,
   1298     0xFF
   1299     );
   1300 
   1301   //
   1302   // Get Device Order from variable
   1303   //
   1304   VarData = BdsLibGetVariableAndSize (
   1305               VAR_LEGACY_DEV_ORDER,
   1306               &gEfiLegacyDevOrderVariableGuid,
   1307               &VarSize
   1308               );
   1309 
   1310   if (NULL != VarData) {
   1311     DevOrder    = (LEGACY_DEV_ORDER_ENTRY *) VarData;
   1312     while (VarData < VarData + VarSize) {
   1313       if (DevOrder->BbsType == BbsType) {
   1314         break;
   1315       }
   1316 
   1317       VarData  = (UINT8 *)((UINTN)VarData + sizeof (BBS_TYPE));
   1318       VarData += *(UINT16 *) VarData;
   1319       DevOrder = (LEGACY_DEV_ORDER_ENTRY *) VarData;
   1320     }
   1321     //
   1322     // Create oneof tag here for FD/HD/CD #1 #2
   1323     //
   1324     for (Index = 0; Index < OptionMenu->MenuNumber; Index++) {
   1325       //
   1326       // Create the string for oneof tag
   1327       //
   1328       UnicodeSPrint (String, sizeof (String), TypeStr, Index);
   1329       StrRef = HiiSetString (CallbackData->BmmHiiHandle, 0, String, NULL);
   1330 
   1331       UnicodeSPrint (String, sizeof (String), TypeStrHelp, Index);
   1332       StrRefHelp = HiiSetString (CallbackData->BmmHiiHandle, 0, String, NULL);
   1333 
   1334       HiiCreateOneOfOpCode (
   1335         mStartOpCodeHandle,
   1336         (EFI_QUESTION_ID) (Key + Index),
   1337         VARSTORE_ID_BOOT_MAINT,
   1338         (UINT16) (Key + Index - CONFIG_OPTION_OFFSET),
   1339         StrRef,
   1340         StrRefHelp,
   1341         EFI_IFR_FLAG_CALLBACK,
   1342         EFI_IFR_NUMERIC_SIZE_1,
   1343         OptionsOpCodeHandle,
   1344         NULL
   1345         );
   1346 
   1347       VarDevOrder = *(UINT16 *) ((UINTN) DevOrder + sizeof (BBS_TYPE) + sizeof (UINT16) + Index * sizeof (UINT16));
   1348 
   1349       if (0xFF00 == (VarDevOrder & 0xFF00)) {
   1350         LegacyOrder[Index]  = 0xFF;
   1351         Pos                 = (VarDevOrder & 0xFF) / 8;
   1352         Bit                 = 7 - ((VarDevOrder & 0xFF) % 8);
   1353         DisMap[Pos] = (UINT8) (DisMap[Pos] | (UINT8) (1 << Bit));
   1354       } else {
   1355         LegacyOrder[Index] = (UINT8) (VarDevOrder & 0xFF);
   1356       }
   1357     }
   1358   }
   1359 
   1360   CopyMem (OldData, LegacyOrder, 100);
   1361 
   1362   HiiFreeOpCodeHandle (OptionsOpCodeHandle);
   1363 
   1364   UpdatePageEnd (CallbackData);
   1365 }
   1366 
   1367 
   1368 /**
   1369   Dispatch the display to the next page based on NewPageId.
   1370 
   1371   @param Private         The BMM context data.
   1372   @param NewPageId       The original page ID.
   1373 
   1374 **/
   1375 VOID
   1376 UpdatePageId (
   1377   BMM_CALLBACK_DATA              *Private,
   1378   UINT16                         NewPageId
   1379   )
   1380 {
   1381   //
   1382   // For the question don't impact the page update, just ignore it.
   1383   //
   1384   if (((NewPageId >= BOOT_OPTION_DEL_QUESTION_ID) && (NewPageId < BOOT_OPTION_DEL_QUESTION_ID + MAX_MENU_NUMBER)) ||
   1385       ((NewPageId >= DRIVER_OPTION_DEL_QUESTION_ID) && (NewPageId < DRIVER_OPTION_DEL_QUESTION_ID + MAX_MENU_NUMBER))) {
   1386     return;
   1387   }
   1388 
   1389   if ((NewPageId < FILE_OPTION_OFFSET) && (NewPageId >= HANDLE_OPTION_OFFSET)) {
   1390     //
   1391     // If we select a handle to add driver option, advance to the add handle description page.
   1392     //
   1393     NewPageId = FORM_DRV_ADD_HANDLE_DESC_ID;
   1394   } else if ((NewPageId == KEY_VALUE_SAVE_AND_EXIT) || (NewPageId == KEY_VALUE_NO_SAVE_AND_EXIT)) {
   1395     //
   1396     // Return to main page after "Save Changes" or "Discard Changes".
   1397     //
   1398     NewPageId = FORM_MAIN_ID;
   1399   } else if ((NewPageId >= TERMINAL_OPTION_OFFSET) && (NewPageId < CONSOLE_OPTION_OFFSET)) {
   1400     NewPageId = FORM_CON_COM_SETUP_ID;
   1401   }
   1402 
   1403   if ((NewPageId > 0) && (NewPageId < MAXIMUM_FORM_ID)) {
   1404     Private->BmmPreviousPageId  = Private->BmmCurrentPageId;
   1405     Private->BmmCurrentPageId   = NewPageId;
   1406   }
   1407 }
   1408