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
RefreshUpdateData(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
UpdatePageStart(IN BMM_CALLBACK_DATA * CallbackData)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
UpdatePageEnd(IN BMM_CALLBACK_DATA * CallbackData)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
CleanUpPage(IN UINT16 LabelId,IN BMM_CALLBACK_DATA * CallbackData)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
BootThisFile(IN BM_FILE_CONTEXT * FileContext)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
UpdateConCOMPage(IN BMM_CALLBACK_DATA * CallbackData)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
UpdateBootDelPage(IN BMM_CALLBACK_DATA * CallbackData)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
UpdateDrvAddHandlePage(IN BMM_CALLBACK_DATA * CallbackData)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
UpdateDrvDelPage(IN BMM_CALLBACK_DATA * CallbackData)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
UpdateDriverAddHandleDescPage(IN BMM_CALLBACK_DATA * CallbackData)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
UpdateConsolePage(IN UINT16 UpdatePageId,IN BM_MENU_OPTION * ConsoleMenu,IN BMM_CALLBACK_DATA * CallbackData)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
UpdateOrderPage(IN UINT16 UpdatePageId,IN BM_MENU_OPTION * OptionMenu,IN BMM_CALLBACK_DATA * CallbackData)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
UpdateBootNextPage(IN BMM_CALLBACK_DATA * CallbackData)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
UpdateTimeOutPage(IN BMM_CALLBACK_DATA * CallbackData)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
UpdateConModePage(IN BMM_CALLBACK_DATA * CallbackData)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
UpdateTerminalPage(IN BMM_CALLBACK_DATA * CallbackData)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
UpdatePageBody(IN UINT16 UpdatePageId,IN BMM_CALLBACK_DATA * CallbackData)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
UpdateSetLegacyDeviceOrderPage(IN UINT16 UpdatePageId,IN BMM_CALLBACK_DATA * CallbackData)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
UpdatePageId(BMM_CALLBACK_DATA * Private,UINT16 NewPageId)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