Home | History | Annotate | Download | only in BootMaintenanceManagerUiLib
      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 "BootMaintenanceManager.h"
     16 
     17 /**
     18  Create the global UpdateData structure.
     19 
     20 **/
     21 VOID
     22 CreateUpdateData (
     23   VOID
     24   )
     25 {
     26   //
     27   // Init OpCode Handle and Allocate space for creation of Buffer
     28   //
     29   mStartOpCodeHandle = HiiAllocateOpCodeHandle ();
     30   ASSERT (mStartOpCodeHandle != NULL);
     31 
     32   mEndOpCodeHandle = HiiAllocateOpCodeHandle ();
     33   ASSERT (mEndOpCodeHandle != NULL);
     34 
     35   //
     36   // Create Hii Extend Label OpCode as the start opcode
     37   //
     38   mStartLabel = (EFI_IFR_GUID_LABEL *) HiiCreateGuidOpCode (mStartOpCodeHandle, &gEfiIfrTianoGuid, NULL, sizeof (EFI_IFR_GUID_LABEL));
     39   mStartLabel->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL;
     40 
     41   //
     42   // Create Hii Extend Label OpCode as the end opcode
     43   //
     44   mEndLabel = (EFI_IFR_GUID_LABEL *) HiiCreateGuidOpCode (mEndOpCodeHandle, &gEfiIfrTianoGuid, NULL, sizeof (EFI_IFR_GUID_LABEL));
     45   mEndLabel->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL;
     46   mEndLabel->Number       = LABEL_END;
     47 }
     48 
     49 /**
     50   Refresh the global UpdateData structure.
     51 
     52 **/
     53 VOID
     54 RefreshUpdateData (
     55   VOID
     56   )
     57 {
     58   //
     59   // Free current updated date
     60   //
     61   if (mStartOpCodeHandle != NULL) {
     62     HiiFreeOpCodeHandle (mStartOpCodeHandle);
     63   }
     64 
     65   //
     66   // Create new OpCode Handle
     67   //
     68   mStartOpCodeHandle = HiiAllocateOpCodeHandle ();
     69 
     70   //
     71   // Create Hii Extend Label OpCode as the start opcode
     72   //
     73   mStartLabel = (EFI_IFR_GUID_LABEL *) HiiCreateGuidOpCode (mStartOpCodeHandle, &gEfiIfrTianoGuid, NULL, sizeof (EFI_IFR_GUID_LABEL));
     74   mStartLabel->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL;
     75 
     76 }
     77 
     78 /**
     79   Add a "Go back to main page" tag in front of the form when there are no
     80   "Apply changes" and "Discard changes" tags in the end of the form.
     81 
     82   @param CallbackData    The BMM context data.
     83 
     84 **/
     85 VOID
     86 UpdatePageStart (
     87   IN BMM_CALLBACK_DATA                *CallbackData
     88   )
     89 {
     90   RefreshUpdateData ();
     91   mStartLabel->Number = CallbackData->BmmCurrentPageId;
     92 
     93   if (!(CallbackData->BmmAskSaveOrNot)) {
     94     //
     95     // Add a "Go back to main page" tag in front of the form when there are no
     96     // "Apply changes" and "Discard changes" tags in the end of the form.
     97     //
     98     HiiCreateGotoOpCode (
     99       mStartOpCodeHandle,
    100       FORM_MAIN_ID,
    101       STRING_TOKEN (STR_FORM_GOTO_MAIN),
    102       STRING_TOKEN (STR_FORM_GOTO_MAIN),
    103       0,
    104       FORM_MAIN_ID
    105       );
    106   }
    107 }
    108 
    109 /**
    110   Create the "Apply changes" and "Discard changes" tags. And
    111   ensure user can return to the main page.
    112 
    113   @param CallbackData    The BMM context data.
    114 
    115 **/
    116 VOID
    117 UpdatePageEnd (
    118   IN BMM_CALLBACK_DATA                *CallbackData
    119   )
    120 {
    121   //
    122   // Create the "Apply changes" and "Discard changes" tags.
    123   //
    124   if (CallbackData->BmmAskSaveOrNot) {
    125     HiiCreateSubTitleOpCode (
    126       mStartOpCodeHandle,
    127       STRING_TOKEN (STR_NULL_STRING),
    128       0,
    129       0,
    130       0
    131       );
    132 
    133     HiiCreateActionOpCode (
    134       mStartOpCodeHandle,
    135       KEY_VALUE_SAVE_AND_EXIT,
    136       STRING_TOKEN (STR_SAVE_AND_EXIT),
    137       STRING_TOKEN (STR_NULL_STRING),
    138       EFI_IFR_FLAG_CALLBACK,
    139       0
    140       );
    141   }
    142 
    143   //
    144   // Ensure user can return to the main page.
    145   //
    146   HiiCreateActionOpCode (
    147     mStartOpCodeHandle,
    148     KEY_VALUE_NO_SAVE_AND_EXIT,
    149     STRING_TOKEN (STR_NO_SAVE_AND_EXIT),
    150     STRING_TOKEN (STR_NULL_STRING),
    151     EFI_IFR_FLAG_CALLBACK,
    152     0
    153     );
    154 
    155   HiiUpdateForm (
    156     CallbackData->BmmHiiHandle,
    157     &mBootMaintGuid,
    158     CallbackData->BmmCurrentPageId,
    159     mStartOpCodeHandle, // Label CallbackData->BmmCurrentPageId
    160     mEndOpCodeHandle    // LABEL_END
    161     );
    162 }
    163 
    164 /**
    165   Clean up the dynamic opcode at label and form specified by both LabelId.
    166 
    167   @param LabelId         It is both the Form ID and Label ID for opcode deletion.
    168   @param CallbackData    The BMM context data.
    169 
    170 **/
    171 VOID
    172 CleanUpPage (
    173   IN UINT16                           LabelId,
    174   IN BMM_CALLBACK_DATA                *CallbackData
    175   )
    176 {
    177   RefreshUpdateData ();
    178 
    179   //
    180   // Remove all op-codes from dynamic page
    181   //
    182   mStartLabel->Number = LabelId;
    183   HiiUpdateForm (
    184     CallbackData->BmmHiiHandle,
    185     &mBootMaintGuid,
    186     LabelId,
    187     mStartOpCodeHandle, // Label LabelId
    188     mEndOpCodeHandle    // LABEL_END
    189     );
    190 }
    191 
    192 /**
    193   Create a list of Goto Opcode for all terminal devices logged
    194   by TerminaMenu. This list will be inserted to form FORM_CON_COM_SETUP_ID.
    195 
    196   @param CallbackData    The BMM context data.
    197 **/
    198 VOID
    199 UpdateConCOMPage (
    200   IN BMM_CALLBACK_DATA                *CallbackData
    201   )
    202 {
    203   BM_MENU_ENTRY       *NewMenuEntry;
    204   UINT16              Index;
    205 
    206   CallbackData->BmmAskSaveOrNot = TRUE;
    207 
    208   UpdatePageStart (CallbackData);
    209 
    210   for (Index = 0; Index < TerminalMenu.MenuNumber; Index++) {
    211     NewMenuEntry = BOpt_GetMenuEntry (&TerminalMenu, Index);
    212 
    213     HiiCreateGotoOpCode (
    214       mStartOpCodeHandle,
    215       FORM_CON_COM_SETUP_ID,
    216       NewMenuEntry->DisplayStringToken,
    217       STRING_TOKEN (STR_NULL_STRING),
    218       EFI_IFR_FLAG_CALLBACK,
    219       (UINT16) (TERMINAL_OPTION_OFFSET + Index)
    220       );
    221   }
    222 
    223   UpdatePageEnd (CallbackData);
    224 }
    225 
    226 
    227 /**
    228   Create a list of boot option from global BootOptionMenu. It
    229   allow user to delete the boot option.
    230 
    231   @param CallbackData    The BMM context data.
    232 
    233 **/
    234 VOID
    235 UpdateBootDelPage (
    236   IN BMM_CALLBACK_DATA                *CallbackData
    237   )
    238 {
    239   BM_MENU_ENTRY   *NewMenuEntry;
    240   BM_LOAD_CONTEXT *NewLoadContext;
    241   UINT16          Index;
    242 
    243   CallbackData->BmmAskSaveOrNot = TRUE;
    244 
    245   UpdatePageStart (CallbackData);
    246 
    247   ASSERT (BootOptionMenu.MenuNumber <= (sizeof (CallbackData->BmmFakeNvData.BootOptionDel) / sizeof (CallbackData->BmmFakeNvData.BootOptionDel[0])));
    248   for (Index = 0; Index < BootOptionMenu.MenuNumber; Index++) {
    249     NewMenuEntry    = BOpt_GetMenuEntry (&BootOptionMenu, Index);
    250     NewLoadContext  = (BM_LOAD_CONTEXT *) NewMenuEntry->VariableContext;
    251     if (NewLoadContext->IsLegacy) {
    252       continue;
    253     }
    254 
    255     NewLoadContext->Deleted = FALSE;
    256 
    257     if (CallbackData->BmmFakeNvData.BootOptionDel[Index] && !CallbackData->BmmFakeNvData.BootOptionDelMark[Index]) {
    258       //
    259       // CallbackData->BmmFakeNvData.BootOptionDel[Index] == TRUE means browser knows this boot option is selected
    260       // CallbackData->BmmFakeNvData.BootOptionDelMark[Index] = FALSE means BDS knows the selected boot option has
    261       // deleted, browser maintains old useless info. So clear this info here, and later update this info to browser
    262       // through HiiSetBrowserData function.
    263       //
    264       CallbackData->BmmFakeNvData.BootOptionDel[Index] = FALSE;
    265       CallbackData->BmmOldFakeNVData.BootOptionDel[Index] = FALSE;
    266     }
    267 
    268     HiiCreateCheckBoxOpCode (
    269       mStartOpCodeHandle,
    270       (EFI_QUESTION_ID) (BOOT_OPTION_DEL_QUESTION_ID + Index),
    271       VARSTORE_ID_BOOT_MAINT,
    272       (UINT16) (BOOT_OPTION_DEL_VAR_OFFSET + Index),
    273       NewMenuEntry->DisplayStringToken,
    274       NewMenuEntry->HelpStringToken,
    275       EFI_IFR_FLAG_CALLBACK,
    276       0,
    277       NULL
    278       );
    279   }
    280   UpdatePageEnd (CallbackData);
    281 }
    282 
    283 /**
    284   Create a lit of driver option from global DriverMenu.
    285 
    286   @param CallbackData    The BMM context data.
    287 
    288 **/
    289 VOID
    290 UpdateDrvAddHandlePage (
    291   IN BMM_CALLBACK_DATA                *CallbackData
    292   )
    293 {
    294   BM_MENU_ENTRY *NewMenuEntry;
    295   UINT16        Index;
    296 
    297   CallbackData->BmmAskSaveOrNot = FALSE;
    298 
    299   UpdatePageStart (CallbackData);
    300 
    301   for (Index = 0; Index < DriverMenu.MenuNumber; Index++) {
    302     NewMenuEntry = BOpt_GetMenuEntry (&DriverMenu, Index);
    303 
    304     HiiCreateGotoOpCode (
    305       mStartOpCodeHandle,
    306       FORM_DRV_ADD_HANDLE_DESC_ID,
    307       NewMenuEntry->DisplayStringToken,
    308       STRING_TOKEN (STR_NULL_STRING),
    309       EFI_IFR_FLAG_CALLBACK,
    310       (UINT16) (HANDLE_OPTION_OFFSET + Index)
    311       );
    312   }
    313 
    314   UpdatePageEnd (CallbackData);
    315 }
    316 
    317 /**
    318   Create a lit of driver option from global DriverOptionMenu. It
    319   allow user to delete the driver option.
    320 
    321   @param CallbackData    The BMM context data.
    322 
    323 **/
    324 VOID
    325 UpdateDrvDelPage (
    326   IN BMM_CALLBACK_DATA                *CallbackData
    327   )
    328 {
    329   BM_MENU_ENTRY   *NewMenuEntry;
    330   BM_LOAD_CONTEXT *NewLoadContext;
    331   UINT16          Index;
    332 
    333   CallbackData->BmmAskSaveOrNot = TRUE;
    334 
    335   UpdatePageStart (CallbackData);
    336 
    337   ASSERT (DriverOptionMenu.MenuNumber <= (sizeof (CallbackData->BmmFakeNvData.DriverOptionDel) / sizeof (CallbackData->BmmFakeNvData.DriverOptionDel[0])));
    338   for (Index = 0; Index < DriverOptionMenu.MenuNumber; Index++) {
    339     NewMenuEntry            = BOpt_GetMenuEntry (&DriverOptionMenu, Index);
    340 
    341     NewLoadContext          = (BM_LOAD_CONTEXT *) NewMenuEntry->VariableContext;
    342     NewLoadContext->Deleted = FALSE;
    343 
    344     if (CallbackData->BmmFakeNvData.DriverOptionDel[Index] && !CallbackData->BmmFakeNvData.DriverOptionDelMark[Index]) {
    345       //
    346       // CallbackData->BmmFakeNvData.BootOptionDel[Index] == TRUE means browser knows this boot option is selected
    347       // CallbackData->BmmFakeNvData.BootOptionDelMark[Index] = FALSE means BDS knows the selected boot option has
    348       // deleted, browser maintains old useless info. So clear this info here, and later update this info to browser
    349       // through HiiSetBrowserData function.
    350       //
    351       CallbackData->BmmFakeNvData.DriverOptionDel[Index] = FALSE;
    352       CallbackData->BmmOldFakeNVData.DriverOptionDel[Index] = FALSE;
    353     }
    354     HiiCreateCheckBoxOpCode (
    355       mStartOpCodeHandle,
    356       (EFI_QUESTION_ID) (DRIVER_OPTION_DEL_QUESTION_ID + Index),
    357       VARSTORE_ID_BOOT_MAINT,
    358       (UINT16) (DRIVER_OPTION_DEL_VAR_OFFSET + Index),
    359       NewMenuEntry->DisplayStringToken,
    360       NewMenuEntry->HelpStringToken,
    361       EFI_IFR_FLAG_CALLBACK,
    362       0,
    363       NULL
    364       );
    365   }
    366 
    367   UpdatePageEnd (CallbackData);
    368 }
    369 
    370 /**
    371   Prepare the page to allow user to add description for
    372   a Driver Option.
    373 
    374   @param CallbackData    The BMM context data.
    375 
    376 **/
    377 VOID
    378 UpdateDriverAddHandleDescPage (
    379   IN BMM_CALLBACK_DATA                *CallbackData
    380   )
    381 {
    382   BM_MENU_ENTRY *NewMenuEntry;
    383 
    384   CallbackData->BmmFakeNvData.DriverAddActive          = 0x01;
    385   CallbackData->BmmFakeNvData.DriverAddForceReconnect  = 0x00;
    386   CallbackData->BmmAskSaveOrNot                        = TRUE;
    387   NewMenuEntry = CallbackData->MenuEntry;
    388 
    389   UpdatePageStart (CallbackData);
    390 
    391   HiiCreateSubTitleOpCode (
    392     mStartOpCodeHandle,
    393     NewMenuEntry->DisplayStringToken,
    394     0,
    395     0,
    396     0
    397     );
    398 
    399   HiiCreateStringOpCode (
    400     mStartOpCodeHandle,
    401     (EFI_QUESTION_ID) DRV_ADD_HANDLE_DESC_QUESTION_ID,
    402     VARSTORE_ID_BOOT_MAINT,
    403     DRV_ADD_HANDLE_DESC_VAR_OFFSET,
    404     STRING_TOKEN (STR_LOAD_OPTION_DESC),
    405     STRING_TOKEN (STR_NULL_STRING),
    406     0,
    407     0,
    408     6,
    409     75,
    410     NULL
    411     );
    412 
    413   HiiCreateCheckBoxOpCode (
    414     mStartOpCodeHandle,
    415     (EFI_QUESTION_ID) DRV_ADD_RECON_QUESTION_ID,
    416     VARSTORE_ID_BOOT_MAINT,
    417     DRV_ADD_RECON_VAR_OFFSET,
    418     STRING_TOKEN (STR_LOAD_OPTION_FORCE_RECON),
    419     STRING_TOKEN (STR_LOAD_OPTION_FORCE_RECON),
    420     0,
    421     0,
    422     NULL
    423     );
    424 
    425   HiiCreateStringOpCode (
    426     mStartOpCodeHandle,
    427     (EFI_QUESTION_ID) DRIVER_ADD_OPTION_QUESTION_ID,
    428     VARSTORE_ID_BOOT_MAINT,
    429     DRIVER_ADD_OPTION_VAR_OFFSET,
    430     STRING_TOKEN (STR_OPTIONAL_DATA),
    431     STRING_TOKEN (STR_NULL_STRING),
    432     0,
    433     0,
    434     6,
    435     75,
    436     NULL
    437     );
    438 
    439   UpdatePageEnd (CallbackData);
    440 }
    441 
    442 /**
    443   Update console page.
    444 
    445   @param UpdatePageId    The form ID to be updated.
    446   @param ConsoleMenu     The console menu list.
    447   @param CallbackData    The BMM context data.
    448 
    449 **/
    450 VOID
    451 UpdateConsolePage (
    452   IN UINT16                           UpdatePageId,
    453   IN BM_MENU_OPTION                   *ConsoleMenu,
    454   IN BMM_CALLBACK_DATA                *CallbackData
    455   )
    456 {
    457   BM_MENU_ENTRY       *NewMenuEntry;
    458   BM_CONSOLE_CONTEXT  *NewConsoleContext;
    459   BM_TERMINAL_CONTEXT *NewTerminalContext;
    460   UINT16              Index;
    461   UINT16              Index2;
    462   UINT8               CheckFlags;
    463   UINT8               *ConsoleCheck;
    464   EFI_QUESTION_ID     QuestionIdBase;
    465   UINT16              VariableOffsetBase;
    466 
    467   CallbackData->BmmAskSaveOrNot = TRUE;
    468 
    469   UpdatePageStart (CallbackData);
    470 
    471   ConsoleCheck       = NULL;
    472   QuestionIdBase     = 0;
    473   VariableOffsetBase = 0;
    474 
    475   switch (UpdatePageId) {
    476   case FORM_CON_IN_ID:
    477     ConsoleCheck       = &CallbackData->BmmFakeNvData.ConsoleInCheck[0];
    478     QuestionIdBase     = CON_IN_DEVICE_QUESTION_ID;
    479     VariableOffsetBase = CON_IN_DEVICE_VAR_OFFSET;
    480     break;
    481 
    482   case FORM_CON_OUT_ID:
    483     ConsoleCheck       = &CallbackData->BmmFakeNvData.ConsoleOutCheck[0];
    484     QuestionIdBase     = CON_OUT_DEVICE_QUESTION_ID;
    485     VariableOffsetBase = CON_OUT_DEVICE_VAR_OFFSET;
    486     break;
    487 
    488   case FORM_CON_ERR_ID:
    489     ConsoleCheck       = &CallbackData->BmmFakeNvData.ConsoleErrCheck[0];
    490     QuestionIdBase     = CON_ERR_DEVICE_QUESTION_ID;
    491     VariableOffsetBase = CON_ERR_DEVICE_VAR_OFFSET;
    492     break;
    493   }
    494   ASSERT (ConsoleCheck != NULL);
    495 
    496   for (Index = 0; ((Index < ConsoleMenu->MenuNumber) && \
    497        (Index < MAX_MENU_NUMBER)) ; Index++) {
    498     CheckFlags = 0;
    499     NewMenuEntry = BOpt_GetMenuEntry (ConsoleMenu, Index);
    500     NewConsoleContext = (BM_CONSOLE_CONTEXT *) NewMenuEntry->VariableContext;
    501     if (NewConsoleContext->IsActive) {
    502       CheckFlags |= EFI_IFR_CHECKBOX_DEFAULT;
    503       ConsoleCheck[Index] = TRUE;
    504     } else {
    505       ConsoleCheck[Index] = FALSE;
    506     }
    507     HiiCreateCheckBoxOpCode (
    508       mStartOpCodeHandle,
    509       (EFI_QUESTION_ID) (QuestionIdBase + Index),
    510       VARSTORE_ID_BOOT_MAINT,
    511       (UINT16) (VariableOffsetBase + Index),
    512       NewMenuEntry->DisplayStringToken,
    513       NewMenuEntry->HelpStringToken,
    514       EFI_IFR_FLAG_CALLBACK,
    515       CheckFlags,
    516       NULL
    517       );
    518   }
    519 
    520   for (Index2 = 0; ((Index2 < TerminalMenu.MenuNumber) && \
    521        (Index2 < MAX_MENU_NUMBER)); Index2++) {
    522     CheckFlags          = 0;
    523     NewMenuEntry        = BOpt_GetMenuEntry (&TerminalMenu, Index2);
    524     NewTerminalContext  = (BM_TERMINAL_CONTEXT *) NewMenuEntry->VariableContext;
    525 
    526     ASSERT (Index < MAX_MENU_NUMBER);
    527     if (((NewTerminalContext->IsConIn != 0) && (UpdatePageId == FORM_CON_IN_ID)) ||
    528         ((NewTerminalContext->IsConOut != 0) && (UpdatePageId == FORM_CON_OUT_ID)) ||
    529         ((NewTerminalContext->IsStdErr != 0) && (UpdatePageId == FORM_CON_ERR_ID))
    530         ) {
    531       CheckFlags |= EFI_IFR_CHECKBOX_DEFAULT;
    532       ConsoleCheck[Index] = TRUE;
    533     } else {
    534       ConsoleCheck[Index] = FALSE;
    535     }
    536     HiiCreateCheckBoxOpCode (
    537       mStartOpCodeHandle,
    538       (EFI_QUESTION_ID) (QuestionIdBase + Index),
    539       VARSTORE_ID_BOOT_MAINT,
    540       (UINT16) (VariableOffsetBase + Index),
    541       NewMenuEntry->DisplayStringToken,
    542       NewMenuEntry->HelpStringToken,
    543       EFI_IFR_FLAG_CALLBACK,
    544       CheckFlags,
    545       NULL
    546       );
    547 
    548     Index++;
    549   }
    550 
    551   UpdatePageEnd (CallbackData);
    552 }
    553 
    554 /**
    555   Update the page's NV Map if user has changed the order
    556   a list. This list can be Boot Order or Driver Order.
    557 
    558   @param UpdatePageId    The form ID to be updated.
    559   @param OptionMenu      The new list.
    560   @param CallbackData    The BMM context data.
    561 
    562 **/
    563 VOID
    564 UpdateOrderPage (
    565   IN UINT16                           UpdatePageId,
    566   IN BM_MENU_OPTION                   *OptionMenu,
    567   IN BMM_CALLBACK_DATA                *CallbackData
    568   )
    569 {
    570   BM_MENU_ENTRY     *NewMenuEntry;
    571   UINT16            Index;
    572   UINT16            OptionIndex;
    573   VOID              *OptionsOpCodeHandle;
    574   BOOLEAN           BootOptionFound;
    575   UINT32            *OptionOrder;
    576   EFI_QUESTION_ID   QuestionId;
    577   UINT16            VarOffset;
    578 
    579   CallbackData->BmmAskSaveOrNot = TRUE;
    580   UpdatePageStart (CallbackData);
    581 
    582   OptionOrder = NULL;
    583   QuestionId = 0;
    584   VarOffset = 0;
    585   switch (UpdatePageId) {
    586 
    587   case FORM_BOOT_CHG_ID:
    588     //
    589     // If the BootOptionOrder in the BmmFakeNvData are same with the date in the BmmOldFakeNVData,
    590     // means all Boot Options has been save in BootOptionMenu, we can get the date from the menu.
    591     // else means browser maintains some uncommitted date which are not saved in BootOptionMenu,
    592     // so we should not get the data from BootOptionMenu to show it.
    593     //
    594     if (CompareMem (CallbackData->BmmFakeNvData.BootOptionOrder, CallbackData->BmmOldFakeNVData.BootOptionOrder, sizeof (CallbackData->BmmFakeNvData.BootOptionOrder)) == 0) {
    595       GetBootOrder (CallbackData);
    596     }
    597     OptionOrder = CallbackData->BmmFakeNvData.BootOptionOrder;
    598     QuestionId = BOOT_OPTION_ORDER_QUESTION_ID;
    599     VarOffset = BOOT_OPTION_ORDER_VAR_OFFSET;
    600     break;
    601 
    602   case FORM_DRV_CHG_ID:
    603     //
    604     // If the DriverOptionOrder in the BmmFakeNvData are same with the date in the BmmOldFakeNVData,
    605     // means all Driver Options has been save in DriverOptionMenu, we can get the DriverOptionOrder from the menu.
    606     // else means browser maintains some uncommitted date which are not saved in DriverOptionMenu,
    607     // so we should not get the data from DriverOptionMenu to show it.
    608     //
    609     if (CompareMem (CallbackData->BmmFakeNvData.DriverOptionOrder, CallbackData->BmmOldFakeNVData.DriverOptionOrder, sizeof (CallbackData->BmmFakeNvData.DriverOptionOrder)) == 0) {
    610       GetDriverOrder (CallbackData);
    611     }
    612     OptionOrder = CallbackData->BmmFakeNvData.DriverOptionOrder;
    613     QuestionId = DRIVER_OPTION_ORDER_QUESTION_ID;
    614     VarOffset = DRIVER_OPTION_ORDER_VAR_OFFSET;
    615     break;
    616   }
    617   ASSERT (OptionOrder != NULL);
    618 
    619   OptionsOpCodeHandle = HiiAllocateOpCodeHandle ();
    620   ASSERT (OptionsOpCodeHandle != NULL);
    621 
    622   NewMenuEntry = NULL;
    623   for (OptionIndex = 0; (OptionOrder[OptionIndex] != 0 && OptionIndex < MAX_MENU_NUMBER); OptionIndex++) {
    624     BootOptionFound = FALSE;
    625     for (Index = 0; Index < OptionMenu->MenuNumber; Index++) {
    626       NewMenuEntry   = BOpt_GetMenuEntry (OptionMenu, Index);
    627       if ((UINT32) (NewMenuEntry->OptionNumber + 1) == OptionOrder[OptionIndex]) {
    628         BootOptionFound = TRUE;
    629         break;
    630       }
    631     }
    632     if (BootOptionFound) {
    633       HiiCreateOneOfOptionOpCode (
    634         OptionsOpCodeHandle,
    635         NewMenuEntry->DisplayStringToken,
    636         0,
    637         EFI_IFR_TYPE_NUM_SIZE_32,
    638         OptionOrder[OptionIndex]
    639         );
    640     }
    641   }
    642 
    643   if (OptionMenu->MenuNumber > 0) {
    644     HiiCreateOrderedListOpCode (
    645       mStartOpCodeHandle,                          // Container for dynamic created opcodes
    646       QuestionId,                                  // Question ID
    647       VARSTORE_ID_BOOT_MAINT,                      // VarStore ID
    648       VarOffset,                                   // Offset in Buffer Storage
    649       STRING_TOKEN (STR_CHANGE_ORDER),             // Question prompt text
    650       STRING_TOKEN (STR_CHANGE_ORDER),             // Question help text
    651       0,                                           // Question flag
    652       0,                                           // Ordered list flag, e.g. EFI_IFR_UNIQUE_SET
    653       EFI_IFR_TYPE_NUM_SIZE_32,                    // Data type of Question value
    654       100,                                         // Maximum container
    655       OptionsOpCodeHandle,                         // Option Opcode list
    656       NULL                                         // Default Opcode is NULL
    657       );
    658   }
    659 
    660   HiiFreeOpCodeHandle (OptionsOpCodeHandle);
    661 
    662   UpdatePageEnd (CallbackData);
    663 
    664 }
    665 
    666 /**
    667   Refresh the text mode page.
    668 
    669   @param CallbackData    The BMM context data.
    670 
    671 **/
    672 VOID
    673 UpdateConModePage (
    674   IN BMM_CALLBACK_DATA                *CallbackData
    675   )
    676 {
    677   UINTN                         Mode;
    678   UINTN                         Index;
    679   UINTN                         Col;
    680   UINTN                         Row;
    681   CHAR16                        ModeString[50];
    682   CHAR16                        *PStr;
    683   UINTN                         MaxMode;
    684   UINTN                         ValidMode;
    685   EFI_STRING_ID                 *ModeToken;
    686   EFI_STATUS                    Status;
    687   VOID                          *OptionsOpCodeHandle;
    688   EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL  *ConOut;
    689 
    690   ConOut    = gST->ConOut;
    691   Index     = 0;
    692   ValidMode = 0;
    693   MaxMode   = (UINTN) (ConOut->Mode->MaxMode);
    694 
    695   CallbackData->BmmAskSaveOrNot = TRUE;
    696 
    697   UpdatePageStart (CallbackData);
    698 
    699   //
    700   // Check valid mode
    701   //
    702   for (Mode = 0; Mode < MaxMode; Mode++) {
    703     Status = ConOut->QueryMode (ConOut, Mode, &Col, &Row);
    704     if (EFI_ERROR (Status)) {
    705       continue;
    706     }
    707     ValidMode++;
    708   }
    709 
    710   if (ValidMode == 0) {
    711     return;
    712   }
    713 
    714   OptionsOpCodeHandle = HiiAllocateOpCodeHandle ();
    715   ASSERT (OptionsOpCodeHandle != NULL);
    716 
    717   ModeToken           = AllocateZeroPool (sizeof (EFI_STRING_ID) * ValidMode);
    718   ASSERT(ModeToken != NULL);
    719 
    720   //
    721   // Determin which mode should be the first entry in menu
    722   //
    723   GetConsoleOutMode (CallbackData);
    724 
    725   //
    726   // Build text mode options
    727   //
    728   for (Mode = 0; Mode < MaxMode; Mode++) {
    729     Status = ConOut->QueryMode (ConOut, Mode, &Col, &Row);
    730     if (EFI_ERROR (Status)) {
    731       continue;
    732     }
    733 
    734     //
    735     // Build mode string Column x Row
    736     //
    737     UnicodeValueToString (ModeString, 0, Col, 0);
    738     PStr = &ModeString[0];
    739     StrnCatS (PStr, ARRAY_SIZE (ModeString), L" x ", StrLen(L" x ") + 1);
    740     PStr = PStr + StrLen (PStr);
    741     UnicodeValueToString (PStr , 0, Row, 0);
    742 
    743     ModeToken[Index] = HiiSetString (CallbackData->BmmHiiHandle, 0, ModeString, NULL);
    744 
    745     if (Mode == CallbackData->BmmFakeNvData.ConsoleOutMode) {
    746       HiiCreateOneOfOptionOpCode (
    747         OptionsOpCodeHandle,
    748         ModeToken[Index],
    749         EFI_IFR_OPTION_DEFAULT,
    750         EFI_IFR_TYPE_NUM_SIZE_16,
    751         (UINT16) Mode
    752         );
    753     } else {
    754       HiiCreateOneOfOptionOpCode (
    755         OptionsOpCodeHandle,
    756         ModeToken[Index],
    757         0,
    758         EFI_IFR_TYPE_NUM_SIZE_16,
    759         (UINT16) Mode
    760         );
    761     }
    762     Index++;
    763   }
    764 
    765   HiiCreateOneOfOpCode (
    766     mStartOpCodeHandle,
    767     (EFI_QUESTION_ID) CON_MODE_QUESTION_ID,
    768     VARSTORE_ID_BOOT_MAINT,
    769     CON_MODE_VAR_OFFSET,
    770     STRING_TOKEN (STR_CON_MODE_SETUP),
    771     STRING_TOKEN (STR_CON_MODE_SETUP),
    772     EFI_IFR_FLAG_RESET_REQUIRED,
    773     EFI_IFR_NUMERIC_SIZE_2,
    774     OptionsOpCodeHandle,
    775     NULL
    776     );
    777 
    778   HiiFreeOpCodeHandle (OptionsOpCodeHandle);
    779   FreePool (ModeToken);
    780 
    781   UpdatePageEnd (CallbackData);
    782 }
    783 
    784  /**
    785   Create the dynamic page which allows user to set the property such as Baud Rate, Data Bits,
    786   Parity, Stop Bits, Terminal Type.
    787 
    788   @param CallbackData    The BMM context data.
    789 
    790 **/
    791 VOID
    792 UpdateTerminalPage (
    793   IN BMM_CALLBACK_DATA                *CallbackData
    794   )
    795 {
    796   UINT8               Index;
    797   UINT8               CheckFlags;
    798   BM_MENU_ENTRY       *NewMenuEntry;
    799   VOID                *OptionsOpCodeHandle;
    800   UINTN               CurrentTerminal;
    801 
    802   CallbackData->BmmAskSaveOrNot = TRUE;
    803 
    804   UpdatePageStart (CallbackData);
    805 
    806   CurrentTerminal = CallbackData->CurrentTerminal;
    807   NewMenuEntry = BOpt_GetMenuEntry (
    808                   &TerminalMenu,
    809                   CurrentTerminal
    810                   );
    811 
    812   if (NewMenuEntry == NULL) {
    813     return ;
    814   }
    815 
    816   OptionsOpCodeHandle = HiiAllocateOpCodeHandle ();
    817   ASSERT (OptionsOpCodeHandle != NULL);
    818 
    819   for (Index = 0; Index < sizeof (BaudRateList) / sizeof (BaudRateList [0]); Index++) {
    820     CheckFlags = 0;
    821     if (BaudRateList[Index].Value == 115200) {
    822       CheckFlags |= EFI_IFR_OPTION_DEFAULT;
    823     }
    824     HiiCreateOneOfOptionOpCode (
    825       OptionsOpCodeHandle,
    826       BaudRateList[Index].StringToken,
    827       CheckFlags,
    828       EFI_IFR_TYPE_NUM_SIZE_8,
    829       Index
    830       );
    831   }
    832 
    833   HiiCreateOneOfOpCode (
    834     mStartOpCodeHandle,
    835     (EFI_QUESTION_ID) (COM_BAUD_RATE_QUESTION_ID + CurrentTerminal),
    836     VARSTORE_ID_BOOT_MAINT,
    837     (UINT16) (COM_BAUD_RATE_VAR_OFFSET + CurrentTerminal),
    838     STRING_TOKEN (STR_COM_BAUD_RATE),
    839     STRING_TOKEN (STR_COM_BAUD_RATE),
    840     EFI_IFR_FLAG_CALLBACK,
    841     EFI_IFR_NUMERIC_SIZE_1,
    842     OptionsOpCodeHandle,
    843     NULL
    844     );
    845 
    846   HiiFreeOpCodeHandle (OptionsOpCodeHandle);
    847   OptionsOpCodeHandle = HiiAllocateOpCodeHandle ();
    848   ASSERT (OptionsOpCodeHandle != NULL);
    849 
    850   for (Index = 0; Index < ARRAY_SIZE (DataBitsList); Index++) {
    851     CheckFlags = 0;
    852 
    853     if (DataBitsList[Index].Value == 8) {
    854       CheckFlags |= EFI_IFR_OPTION_DEFAULT;
    855     }
    856 
    857     HiiCreateOneOfOptionOpCode (
    858       OptionsOpCodeHandle,
    859       DataBitsList[Index].StringToken,
    860       CheckFlags,
    861       EFI_IFR_TYPE_NUM_SIZE_8,
    862       Index
    863       );
    864   }
    865 
    866   HiiCreateOneOfOpCode (
    867     mStartOpCodeHandle,
    868     (EFI_QUESTION_ID) (COM_DATA_RATE_QUESTION_ID + CurrentTerminal),
    869     VARSTORE_ID_BOOT_MAINT,
    870     (UINT16) (COM_DATA_RATE_VAR_OFFSET + CurrentTerminal),
    871     STRING_TOKEN (STR_COM_DATA_BITS),
    872     STRING_TOKEN (STR_COM_DATA_BITS),
    873     EFI_IFR_FLAG_CALLBACK,
    874     EFI_IFR_NUMERIC_SIZE_1,
    875     OptionsOpCodeHandle,
    876     NULL
    877     );
    878 
    879   HiiFreeOpCodeHandle (OptionsOpCodeHandle);
    880   OptionsOpCodeHandle = HiiAllocateOpCodeHandle ();
    881   ASSERT (OptionsOpCodeHandle != NULL);
    882 
    883   for (Index = 0; Index < ARRAY_SIZE (ParityList); Index++) {
    884     CheckFlags = 0;
    885     if (ParityList[Index].Value ==  NoParity) {
    886       CheckFlags |= EFI_IFR_OPTION_DEFAULT;
    887     }
    888 
    889     HiiCreateOneOfOptionOpCode (
    890       OptionsOpCodeHandle,
    891       ParityList[Index].StringToken,
    892       CheckFlags,
    893       EFI_IFR_TYPE_NUM_SIZE_8,
    894       Index
    895       );
    896   }
    897 
    898   HiiCreateOneOfOpCode (
    899     mStartOpCodeHandle,
    900     (EFI_QUESTION_ID) (COM_PARITY_QUESTION_ID + CurrentTerminal),
    901     VARSTORE_ID_BOOT_MAINT,
    902     (UINT16) (COM_PARITY_VAR_OFFSET + CurrentTerminal),
    903     STRING_TOKEN (STR_COM_PARITY),
    904     STRING_TOKEN (STR_COM_PARITY),
    905     EFI_IFR_FLAG_CALLBACK,
    906     EFI_IFR_NUMERIC_SIZE_1,
    907     OptionsOpCodeHandle,
    908     NULL
    909     );
    910 
    911   HiiFreeOpCodeHandle (OptionsOpCodeHandle);
    912   OptionsOpCodeHandle = HiiAllocateOpCodeHandle ();
    913   ASSERT (OptionsOpCodeHandle != NULL);
    914 
    915   for (Index = 0; Index < ARRAY_SIZE (StopBitsList); Index++) {
    916     CheckFlags = 0;
    917     if (StopBitsList[Index].Value == OneStopBit) {
    918       CheckFlags |= EFI_IFR_OPTION_DEFAULT;
    919     }
    920 
    921     HiiCreateOneOfOptionOpCode (
    922       OptionsOpCodeHandle,
    923       StopBitsList[Index].StringToken,
    924       CheckFlags,
    925       EFI_IFR_TYPE_NUM_SIZE_8,
    926       Index
    927       );
    928   }
    929 
    930   HiiCreateOneOfOpCode (
    931     mStartOpCodeHandle,
    932     (EFI_QUESTION_ID) (COM_STOP_BITS_QUESTION_ID + CurrentTerminal),
    933     VARSTORE_ID_BOOT_MAINT,
    934     (UINT16) (COM_STOP_BITS_VAR_OFFSET + CurrentTerminal),
    935     STRING_TOKEN (STR_COM_STOP_BITS),
    936     STRING_TOKEN (STR_COM_STOP_BITS),
    937     EFI_IFR_FLAG_CALLBACK,
    938     EFI_IFR_NUMERIC_SIZE_1,
    939     OptionsOpCodeHandle,
    940     NULL
    941     );
    942 
    943   HiiFreeOpCodeHandle (OptionsOpCodeHandle);
    944   OptionsOpCodeHandle = HiiAllocateOpCodeHandle ();
    945   ASSERT (OptionsOpCodeHandle != NULL);
    946 
    947   for (Index = 0; Index < ARRAY_SIZE (TerminalType); Index++) {
    948     CheckFlags = 0;
    949     if (Index == 0) {
    950       CheckFlags |= EFI_IFR_OPTION_DEFAULT;
    951     }
    952 
    953     HiiCreateOneOfOptionOpCode (
    954       OptionsOpCodeHandle,
    955       (EFI_STRING_ID) TerminalType[Index],
    956       CheckFlags,
    957       EFI_IFR_TYPE_NUM_SIZE_8,
    958       Index
    959       );
    960   }
    961 
    962   HiiCreateOneOfOpCode (
    963     mStartOpCodeHandle,
    964     (EFI_QUESTION_ID) (COM_TERMINAL_QUESTION_ID + CurrentTerminal),
    965     VARSTORE_ID_BOOT_MAINT,
    966     (UINT16) (COM_TERMINAL_VAR_OFFSET + CurrentTerminal),
    967     STRING_TOKEN (STR_COM_TERMI_TYPE),
    968     STRING_TOKEN (STR_COM_TERMI_TYPE),
    969     EFI_IFR_FLAG_CALLBACK,
    970     EFI_IFR_NUMERIC_SIZE_1,
    971     OptionsOpCodeHandle,
    972     NULL
    973     );
    974 
    975   HiiFreeOpCodeHandle (OptionsOpCodeHandle);
    976   OptionsOpCodeHandle = HiiAllocateOpCodeHandle ();
    977   ASSERT (OptionsOpCodeHandle != NULL);
    978 
    979   for (Index = 0; Index < ARRAY_SIZE (mFlowControlType); Index++) {
    980   CheckFlags = 0;
    981     if (Index == 0) {
    982       CheckFlags |= EFI_IFR_OPTION_DEFAULT;
    983     }
    984     HiiCreateOneOfOptionOpCode (
    985       OptionsOpCodeHandle,
    986       (EFI_STRING_ID) mFlowControlType[Index],
    987       CheckFlags,
    988       EFI_IFR_TYPE_NUM_SIZE_8,
    989       mFlowControlValue[Index]
    990       );
    991   }
    992 
    993   HiiCreateOneOfOpCode (
    994     mStartOpCodeHandle,
    995     (EFI_QUESTION_ID) (COM_FLOWCONTROL_QUESTION_ID + CurrentTerminal),
    996     VARSTORE_ID_BOOT_MAINT,
    997     (UINT16) (COM_FLOWCONTROL_VAR_OFFSET + CurrentTerminal),
    998     STRING_TOKEN (STR_COM_FLOW_CONTROL),
    999     STRING_TOKEN (STR_COM_FLOW_CONTROL),
   1000     EFI_IFR_FLAG_CALLBACK,
   1001     EFI_IFR_NUMERIC_SIZE_1,
   1002     OptionsOpCodeHandle,
   1003     NULL
   1004     );
   1005 
   1006   HiiFreeOpCodeHandle (OptionsOpCodeHandle);
   1007 
   1008   UpdatePageEnd (CallbackData);
   1009 }
   1010 
   1011 /**
   1012 Update add boot/driver option page.
   1013 
   1014 @param CallbackData    The BMM context data.
   1015 @param FormId             The form ID to be updated.
   1016 @param DevicePath       Device path.
   1017 
   1018 **/
   1019 VOID
   1020 UpdateOptionPage(
   1021   IN   BMM_CALLBACK_DATA        *CallbackData,
   1022   IN   EFI_FORM_ID              FormId,
   1023   IN   EFI_DEVICE_PATH_PROTOCOL *DevicePath
   1024   )
   1025 {
   1026   CHAR16                *String;
   1027   EFI_STRING_ID         StringToken;
   1028 
   1029   String = NULL;
   1030 
   1031   if (DevicePath != NULL){
   1032     String = ExtractFileNameFromDevicePath(DevicePath);
   1033   }
   1034   if (String == NULL) {
   1035     String = HiiGetString (CallbackData->BmmHiiHandle, STRING_TOKEN (STR_NULL_STRING), NULL);
   1036     ASSERT (String != NULL);
   1037   }
   1038 
   1039   StringToken = HiiSetString (CallbackData->BmmHiiHandle, 0, String, NULL);
   1040   FreePool (String);
   1041 
   1042   if(FormId == FORM_BOOT_ADD_ID){
   1043     if (!CallbackData->BmmFakeNvData.BootOptionChanged) {
   1044       ZeroMem (CallbackData->BmmFakeNvData.BootOptionalData, sizeof (CallbackData->BmmFakeNvData.BootOptionalData));
   1045       ZeroMem (CallbackData->BmmFakeNvData.BootDescriptionData, sizeof (CallbackData->BmmFakeNvData.BootDescriptionData));
   1046       ZeroMem (CallbackData->BmmOldFakeNVData.BootOptionalData, sizeof (CallbackData->BmmOldFakeNVData.BootOptionalData));
   1047       ZeroMem (CallbackData->BmmOldFakeNVData.BootDescriptionData, sizeof (CallbackData->BmmOldFakeNVData.BootDescriptionData));
   1048     }
   1049   } else if (FormId == FORM_DRV_ADD_FILE_ID){
   1050     if (!CallbackData->BmmFakeNvData.DriverOptionChanged) {
   1051       ZeroMem (CallbackData->BmmFakeNvData.DriverOptionalData, sizeof (CallbackData->BmmFakeNvData.DriverOptionalData));
   1052       ZeroMem (CallbackData->BmmFakeNvData.DriverDescriptionData, sizeof (CallbackData->BmmFakeNvData.DriverDescriptionData));
   1053       ZeroMem (CallbackData->BmmOldFakeNVData.DriverOptionalData, sizeof (CallbackData->BmmOldFakeNVData.DriverOptionalData));
   1054       ZeroMem (CallbackData->BmmOldFakeNVData.DriverDescriptionData, sizeof (CallbackData->BmmOldFakeNVData.DriverDescriptionData));
   1055     }
   1056   }
   1057 
   1058   RefreshUpdateData();
   1059   mStartLabel->Number = FormId;
   1060 
   1061   HiiCreateSubTitleOpCode (
   1062     mStartOpCodeHandle,
   1063     StringToken,
   1064     0,
   1065     0,
   1066     0
   1067     );
   1068 
   1069   HiiUpdateForm (
   1070     CallbackData->BmmHiiHandle,
   1071     &mBootMaintGuid,
   1072     FormId,
   1073     mStartOpCodeHandle,// Label FormId
   1074     mEndOpCodeHandle   // LABEL_END
   1075     );
   1076 }
   1077 
   1078 /**
   1079   Dispatch the correct update page function to call based on
   1080   the UpdatePageId.
   1081 
   1082   @param UpdatePageId    The form ID.
   1083   @param CallbackData    The BMM context data.
   1084 
   1085 **/
   1086 VOID
   1087 UpdatePageBody (
   1088   IN UINT16                           UpdatePageId,
   1089   IN BMM_CALLBACK_DATA                *CallbackData
   1090   )
   1091 {
   1092   CleanUpPage (UpdatePageId, CallbackData);
   1093   switch (UpdatePageId) {
   1094   case FORM_CON_IN_ID:
   1095     UpdateConsolePage (UpdatePageId, &ConsoleInpMenu, CallbackData);
   1096     break;
   1097 
   1098   case FORM_CON_OUT_ID:
   1099     UpdateConsolePage (UpdatePageId, &ConsoleOutMenu, CallbackData);
   1100     break;
   1101 
   1102   case FORM_CON_ERR_ID:
   1103     UpdateConsolePage (UpdatePageId, &ConsoleErrMenu, CallbackData);
   1104     break;
   1105 
   1106   case FORM_BOOT_CHG_ID:
   1107     UpdateOrderPage (UpdatePageId, &BootOptionMenu, CallbackData);
   1108     break;
   1109 
   1110   case FORM_DRV_CHG_ID:
   1111     UpdateOrderPage (UpdatePageId, &DriverOptionMenu, CallbackData);
   1112     break;
   1113 
   1114   default:
   1115     break;
   1116   }
   1117 }
   1118 
   1119 /**
   1120   Dispatch the display to the next page based on NewPageId.
   1121 
   1122   @param Private         The BMM context data.
   1123   @param NewPageId       The original page ID.
   1124 
   1125 **/
   1126 VOID
   1127 UpdatePageId (
   1128   BMM_CALLBACK_DATA              *Private,
   1129   UINT16                         NewPageId
   1130   )
   1131 {
   1132   if ((NewPageId < FILE_OPTION_OFFSET) && (NewPageId >= HANDLE_OPTION_OFFSET)) {
   1133     //
   1134     // If we select a handle to add driver option, advance to the add handle description page.
   1135     //
   1136     NewPageId = FORM_DRV_ADD_HANDLE_DESC_ID;
   1137   } else if ((NewPageId == KEY_VALUE_SAVE_AND_EXIT) || (NewPageId == KEY_VALUE_NO_SAVE_AND_EXIT)) {
   1138     //
   1139     // Return to main page after "Save Changes" or "Discard Changes".
   1140     //
   1141     NewPageId = FORM_MAIN_ID;
   1142   } else if ((NewPageId >= TERMINAL_OPTION_OFFSET) && (NewPageId < CONSOLE_OPTION_OFFSET)) {
   1143     NewPageId = FORM_CON_COM_SETUP_ID;
   1144   }
   1145 
   1146   if ((NewPageId > 0) && (NewPageId < MAXIMUM_FORM_ID)) {
   1147     Private->BmmPreviousPageId  = Private->BmmCurrentPageId;
   1148     Private->BmmCurrentPageId   = NewPageId;
   1149   }
   1150 }
   1151