1 /** @file
2 Dynamically update the pages.
3 
4 Copyright (c) 2004 - 2018, Intel Corporation. All rights reserved.<BR>
5 SPDX-License-Identifier: BSD-2-Clause-Patent
6 
7 **/
8 
9 #include "BootMaintenanceManager.h"
10 
11 /**
12  Create the global UpdateData structure.
13 
14 **/
15 VOID
CreateUpdateData(VOID)16 CreateUpdateData (
17   VOID
18   )
19 {
20   //
21   // Init OpCode Handle and Allocate space for creation of Buffer
22   //
23   mStartOpCodeHandle = HiiAllocateOpCodeHandle ();
24   ASSERT (mStartOpCodeHandle != NULL);
25 
26   mEndOpCodeHandle = HiiAllocateOpCodeHandle ();
27   ASSERT (mEndOpCodeHandle != NULL);
28 
29   //
30   // Create Hii Extend Label OpCode as the start opcode
31   //
32   mStartLabel = (EFI_IFR_GUID_LABEL *) HiiCreateGuidOpCode (mStartOpCodeHandle, &gEfiIfrTianoGuid, NULL, sizeof (EFI_IFR_GUID_LABEL));
33   mStartLabel->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL;
34 
35   //
36   // Create Hii Extend Label OpCode as the end opcode
37   //
38   mEndLabel = (EFI_IFR_GUID_LABEL *) HiiCreateGuidOpCode (mEndOpCodeHandle, &gEfiIfrTianoGuid, NULL, sizeof (EFI_IFR_GUID_LABEL));
39   mEndLabel->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL;
40   mEndLabel->Number       = LABEL_END;
41 }
42 
43 /**
44   Refresh the global UpdateData structure.
45 
46 **/
47 VOID
RefreshUpdateData(VOID)48 RefreshUpdateData (
49   VOID
50   )
51 {
52   //
53   // Free current updated date
54   //
55   if (mStartOpCodeHandle != NULL) {
56     HiiFreeOpCodeHandle (mStartOpCodeHandle);
57   }
58 
59   //
60   // Create new OpCode Handle
61   //
62   mStartOpCodeHandle = HiiAllocateOpCodeHandle ();
63 
64   //
65   // Create Hii Extend Label OpCode as the start opcode
66   //
67   mStartLabel = (EFI_IFR_GUID_LABEL *) HiiCreateGuidOpCode (mStartOpCodeHandle, &gEfiIfrTianoGuid, NULL, sizeof (EFI_IFR_GUID_LABEL));
68   mStartLabel->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL;
69 
70 }
71 
72 /**
73   Add a "Go back to main page" tag in front of the form when there are no
74   "Apply changes" and "Discard changes" tags in the end of the form.
75 
76   @param CallbackData    The BMM context data.
77 
78 **/
79 VOID
UpdatePageStart(IN BMM_CALLBACK_DATA * CallbackData)80 UpdatePageStart (
81   IN BMM_CALLBACK_DATA                *CallbackData
82   )
83 {
84   RefreshUpdateData ();
85   mStartLabel->Number = CallbackData->BmmCurrentPageId;
86 
87   if (!(CallbackData->BmmAskSaveOrNot)) {
88     //
89     // Add a "Go back to main page" tag in front of the form when there are no
90     // "Apply changes" and "Discard changes" tags in the end of the form.
91     //
92     HiiCreateGotoOpCode (
93       mStartOpCodeHandle,
94       FORM_MAIN_ID,
95       STRING_TOKEN (STR_FORM_GOTO_MAIN),
96       STRING_TOKEN (STR_FORM_GOTO_MAIN),
97       0,
98       FORM_MAIN_ID
99       );
100   }
101 }
102 
103 /**
104   Create the "Apply changes" and "Discard changes" tags. And
105   ensure user can return to the main page.
106 
107   @param CallbackData    The BMM context data.
108 
109 **/
110 VOID
UpdatePageEnd(IN BMM_CALLBACK_DATA * CallbackData)111 UpdatePageEnd (
112   IN BMM_CALLBACK_DATA                *CallbackData
113   )
114 {
115   //
116   // Create the "Apply changes" and "Discard changes" tags.
117   //
118   if (CallbackData->BmmAskSaveOrNot) {
119     HiiCreateSubTitleOpCode (
120       mStartOpCodeHandle,
121       STRING_TOKEN (STR_NULL_STRING),
122       0,
123       0,
124       0
125       );
126 
127     HiiCreateActionOpCode (
128       mStartOpCodeHandle,
129       KEY_VALUE_SAVE_AND_EXIT,
130       STRING_TOKEN (STR_SAVE_AND_EXIT),
131       STRING_TOKEN (STR_NULL_STRING),
132       EFI_IFR_FLAG_CALLBACK,
133       0
134       );
135   }
136 
137   //
138   // Ensure user can return to the main page.
139   //
140   HiiCreateActionOpCode (
141     mStartOpCodeHandle,
142     KEY_VALUE_NO_SAVE_AND_EXIT,
143     STRING_TOKEN (STR_NO_SAVE_AND_EXIT),
144     STRING_TOKEN (STR_NULL_STRING),
145     EFI_IFR_FLAG_CALLBACK,
146     0
147     );
148 
149   HiiUpdateForm (
150     CallbackData->BmmHiiHandle,
151     &mBootMaintGuid,
152     CallbackData->BmmCurrentPageId,
153     mStartOpCodeHandle, // Label CallbackData->BmmCurrentPageId
154     mEndOpCodeHandle    // LABEL_END
155     );
156 }
157 
158 /**
159   Clean up the dynamic opcode at label and form specified by both LabelId.
160 
161   @param LabelId         It is both the Form ID and Label ID for opcode deletion.
162   @param CallbackData    The BMM context data.
163 
164 **/
165 VOID
CleanUpPage(IN UINT16 LabelId,IN BMM_CALLBACK_DATA * CallbackData)166 CleanUpPage (
167   IN UINT16                           LabelId,
168   IN BMM_CALLBACK_DATA                *CallbackData
169   )
170 {
171   RefreshUpdateData ();
172 
173   //
174   // Remove all op-codes from dynamic page
175   //
176   mStartLabel->Number = LabelId;
177   HiiUpdateForm (
178     CallbackData->BmmHiiHandle,
179     &mBootMaintGuid,
180     LabelId,
181     mStartOpCodeHandle, // Label LabelId
182     mEndOpCodeHandle    // LABEL_END
183     );
184 }
185 
186 /**
187   Create a list of Goto Opcode for all terminal devices logged
188   by TerminaMenu. This list will be inserted to form FORM_CON_COM_SETUP_ID.
189 
190   @param CallbackData    The BMM context data.
191 **/
192 VOID
UpdateConCOMPage(IN BMM_CALLBACK_DATA * CallbackData)193 UpdateConCOMPage (
194   IN BMM_CALLBACK_DATA                *CallbackData
195   )
196 {
197   BM_MENU_ENTRY       *NewMenuEntry;
198   UINT16              Index;
199 
200   CallbackData->BmmAskSaveOrNot = TRUE;
201 
202   UpdatePageStart (CallbackData);
203 
204   for (Index = 0; Index < TerminalMenu.MenuNumber; Index++) {
205     NewMenuEntry = BOpt_GetMenuEntry (&TerminalMenu, Index);
206 
207     HiiCreateGotoOpCode (
208       mStartOpCodeHandle,
209       FORM_CON_COM_SETUP_ID,
210       NewMenuEntry->DisplayStringToken,
211       STRING_TOKEN (STR_NULL_STRING),
212       EFI_IFR_FLAG_CALLBACK,
213       (UINT16) (TERMINAL_OPTION_OFFSET + Index)
214       );
215   }
216 
217   UpdatePageEnd (CallbackData);
218 }
219 
220 
221 /**
222   Create a list of boot option from global BootOptionMenu. It
223   allow user to delete the boot option.
224 
225   @param CallbackData    The BMM context data.
226 
227 **/
228 VOID
UpdateBootDelPage(IN BMM_CALLBACK_DATA * CallbackData)229 UpdateBootDelPage (
230   IN BMM_CALLBACK_DATA                *CallbackData
231   )
232 {
233   BM_MENU_ENTRY   *NewMenuEntry;
234   BM_LOAD_CONTEXT *NewLoadContext;
235   UINT16          Index;
236 
237   CallbackData->BmmAskSaveOrNot = TRUE;
238 
239   UpdatePageStart (CallbackData);
240 
241   ASSERT (BootOptionMenu.MenuNumber <= (sizeof (CallbackData->BmmFakeNvData.BootOptionDel) / sizeof (CallbackData->BmmFakeNvData.BootOptionDel[0])));
242   for (Index = 0; Index < BootOptionMenu.MenuNumber; Index++) {
243     NewMenuEntry    = BOpt_GetMenuEntry (&BootOptionMenu, Index);
244     NewLoadContext  = (BM_LOAD_CONTEXT *) NewMenuEntry->VariableContext;
245     if (NewLoadContext->IsLegacy) {
246       continue;
247     }
248 
249     NewLoadContext->Deleted = FALSE;
250 
251     if (CallbackData->BmmFakeNvData.BootOptionDel[Index] && !CallbackData->BmmFakeNvData.BootOptionDelMark[Index]) {
252       //
253       // CallbackData->BmmFakeNvData.BootOptionDel[Index] == TRUE means browser knows this boot option is selected
254       // CallbackData->BmmFakeNvData.BootOptionDelMark[Index] = FALSE means BDS knows the selected boot option has
255       // deleted, browser maintains old useless info. So clear this info here, and later update this info to browser
256       // through HiiSetBrowserData function.
257       //
258       CallbackData->BmmFakeNvData.BootOptionDel[Index] = FALSE;
259       CallbackData->BmmOldFakeNVData.BootOptionDel[Index] = FALSE;
260     }
261 
262     HiiCreateCheckBoxOpCode (
263       mStartOpCodeHandle,
264       (EFI_QUESTION_ID) (BOOT_OPTION_DEL_QUESTION_ID + Index),
265       VARSTORE_ID_BOOT_MAINT,
266       (UINT16) (BOOT_OPTION_DEL_VAR_OFFSET + Index),
267       NewMenuEntry->DisplayStringToken,
268       NewMenuEntry->HelpStringToken,
269       EFI_IFR_FLAG_CALLBACK,
270       0,
271       NULL
272       );
273   }
274   UpdatePageEnd (CallbackData);
275 }
276 
277 /**
278   Create a lit of driver option from global DriverMenu.
279 
280   @param CallbackData    The BMM context data.
281 
282 **/
283 VOID
UpdateDrvAddHandlePage(IN BMM_CALLBACK_DATA * CallbackData)284 UpdateDrvAddHandlePage (
285   IN BMM_CALLBACK_DATA                *CallbackData
286   )
287 {
288   BM_MENU_ENTRY *NewMenuEntry;
289   UINT16        Index;
290 
291   CallbackData->BmmAskSaveOrNot = FALSE;
292 
293   UpdatePageStart (CallbackData);
294 
295   for (Index = 0; Index < DriverMenu.MenuNumber; Index++) {
296     NewMenuEntry = BOpt_GetMenuEntry (&DriverMenu, Index);
297 
298     HiiCreateGotoOpCode (
299       mStartOpCodeHandle,
300       FORM_DRV_ADD_HANDLE_DESC_ID,
301       NewMenuEntry->DisplayStringToken,
302       STRING_TOKEN (STR_NULL_STRING),
303       EFI_IFR_FLAG_CALLBACK,
304       (UINT16) (HANDLE_OPTION_OFFSET + Index)
305       );
306   }
307 
308   UpdatePageEnd (CallbackData);
309 }
310 
311 /**
312   Create a lit of driver option from global DriverOptionMenu. It
313   allow user to delete the driver option.
314 
315   @param CallbackData    The BMM context data.
316 
317 **/
318 VOID
UpdateDrvDelPage(IN BMM_CALLBACK_DATA * CallbackData)319 UpdateDrvDelPage (
320   IN BMM_CALLBACK_DATA                *CallbackData
321   )
322 {
323   BM_MENU_ENTRY   *NewMenuEntry;
324   BM_LOAD_CONTEXT *NewLoadContext;
325   UINT16          Index;
326 
327   CallbackData->BmmAskSaveOrNot = TRUE;
328 
329   UpdatePageStart (CallbackData);
330 
331   ASSERT (DriverOptionMenu.MenuNumber <= (sizeof (CallbackData->BmmFakeNvData.DriverOptionDel) / sizeof (CallbackData->BmmFakeNvData.DriverOptionDel[0])));
332   for (Index = 0; Index < DriverOptionMenu.MenuNumber; Index++) {
333     NewMenuEntry            = BOpt_GetMenuEntry (&DriverOptionMenu, Index);
334 
335     NewLoadContext          = (BM_LOAD_CONTEXT *) NewMenuEntry->VariableContext;
336     NewLoadContext->Deleted = FALSE;
337 
338     if (CallbackData->BmmFakeNvData.DriverOptionDel[Index] && !CallbackData->BmmFakeNvData.DriverOptionDelMark[Index]) {
339       //
340       // CallbackData->BmmFakeNvData.BootOptionDel[Index] == TRUE means browser knows this boot option is selected
341       // CallbackData->BmmFakeNvData.BootOptionDelMark[Index] = FALSE means BDS knows the selected boot option has
342       // deleted, browser maintains old useless info. So clear this info here, and later update this info to browser
343       // through HiiSetBrowserData function.
344       //
345       CallbackData->BmmFakeNvData.DriverOptionDel[Index] = FALSE;
346       CallbackData->BmmOldFakeNVData.DriverOptionDel[Index] = FALSE;
347     }
348     HiiCreateCheckBoxOpCode (
349       mStartOpCodeHandle,
350       (EFI_QUESTION_ID) (DRIVER_OPTION_DEL_QUESTION_ID + Index),
351       VARSTORE_ID_BOOT_MAINT,
352       (UINT16) (DRIVER_OPTION_DEL_VAR_OFFSET + Index),
353       NewMenuEntry->DisplayStringToken,
354       NewMenuEntry->HelpStringToken,
355       EFI_IFR_FLAG_CALLBACK,
356       0,
357       NULL
358       );
359   }
360 
361   UpdatePageEnd (CallbackData);
362 }
363 
364 /**
365   Prepare the page to allow user to add description for
366   a Driver Option.
367 
368   @param CallbackData    The BMM context data.
369 
370 **/
371 VOID
UpdateDriverAddHandleDescPage(IN BMM_CALLBACK_DATA * CallbackData)372 UpdateDriverAddHandleDescPage (
373   IN BMM_CALLBACK_DATA                *CallbackData
374   )
375 {
376   BM_MENU_ENTRY *NewMenuEntry;
377 
378   CallbackData->BmmFakeNvData.DriverAddActive          = 0x01;
379   CallbackData->BmmFakeNvData.DriverAddForceReconnect  = 0x00;
380   CallbackData->BmmAskSaveOrNot                        = TRUE;
381   NewMenuEntry = CallbackData->MenuEntry;
382 
383   UpdatePageStart (CallbackData);
384 
385   HiiCreateSubTitleOpCode (
386     mStartOpCodeHandle,
387     NewMenuEntry->DisplayStringToken,
388     0,
389     0,
390     0
391     );
392 
393   HiiCreateStringOpCode (
394     mStartOpCodeHandle,
395     (EFI_QUESTION_ID) DRV_ADD_HANDLE_DESC_QUESTION_ID,
396     VARSTORE_ID_BOOT_MAINT,
397     DRV_ADD_HANDLE_DESC_VAR_OFFSET,
398     STRING_TOKEN (STR_LOAD_OPTION_DESC),
399     STRING_TOKEN (STR_NULL_STRING),
400     0,
401     0,
402     6,
403     75,
404     NULL
405     );
406 
407   HiiCreateCheckBoxOpCode (
408     mStartOpCodeHandle,
409     (EFI_QUESTION_ID) DRV_ADD_RECON_QUESTION_ID,
410     VARSTORE_ID_BOOT_MAINT,
411     DRV_ADD_RECON_VAR_OFFSET,
412     STRING_TOKEN (STR_LOAD_OPTION_FORCE_RECON),
413     STRING_TOKEN (STR_LOAD_OPTION_FORCE_RECON),
414     0,
415     0,
416     NULL
417     );
418 
419   HiiCreateStringOpCode (
420     mStartOpCodeHandle,
421     (EFI_QUESTION_ID) DRIVER_ADD_OPTION_QUESTION_ID,
422     VARSTORE_ID_BOOT_MAINT,
423     DRIVER_ADD_OPTION_VAR_OFFSET,
424     STRING_TOKEN (STR_OPTIONAL_DATA),
425     STRING_TOKEN (STR_NULL_STRING),
426     0,
427     0,
428     6,
429     75,
430     NULL
431     );
432 
433   UpdatePageEnd (CallbackData);
434 }
435 
436 /**
437   Update console page.
438 
439   @param UpdatePageId    The form ID to be updated.
440   @param ConsoleMenu     The console menu list.
441   @param CallbackData    The BMM context data.
442 
443 **/
444 VOID
UpdateConsolePage(IN UINT16 UpdatePageId,IN BM_MENU_OPTION * ConsoleMenu,IN BMM_CALLBACK_DATA * CallbackData)445 UpdateConsolePage (
446   IN UINT16                           UpdatePageId,
447   IN BM_MENU_OPTION                   *ConsoleMenu,
448   IN BMM_CALLBACK_DATA                *CallbackData
449   )
450 {
451   BM_MENU_ENTRY       *NewMenuEntry;
452   BM_CONSOLE_CONTEXT  *NewConsoleContext;
453   BM_TERMINAL_CONTEXT *NewTerminalContext;
454   UINT16              Index;
455   UINT16              Index2;
456   UINT8               CheckFlags;
457   UINT8               *ConsoleCheck;
458   EFI_QUESTION_ID     QuestionIdBase;
459   UINT16              VariableOffsetBase;
460 
461   CallbackData->BmmAskSaveOrNot = TRUE;
462 
463   UpdatePageStart (CallbackData);
464 
465   ConsoleCheck       = NULL;
466   QuestionIdBase     = 0;
467   VariableOffsetBase = 0;
468 
469   switch (UpdatePageId) {
470   case FORM_CON_IN_ID:
471     ConsoleCheck       = &CallbackData->BmmFakeNvData.ConsoleInCheck[0];
472     QuestionIdBase     = CON_IN_DEVICE_QUESTION_ID;
473     VariableOffsetBase = CON_IN_DEVICE_VAR_OFFSET;
474     break;
475 
476   case FORM_CON_OUT_ID:
477     ConsoleCheck       = &CallbackData->BmmFakeNvData.ConsoleOutCheck[0];
478     QuestionIdBase     = CON_OUT_DEVICE_QUESTION_ID;
479     VariableOffsetBase = CON_OUT_DEVICE_VAR_OFFSET;
480     break;
481 
482   case FORM_CON_ERR_ID:
483     ConsoleCheck       = &CallbackData->BmmFakeNvData.ConsoleErrCheck[0];
484     QuestionIdBase     = CON_ERR_DEVICE_QUESTION_ID;
485     VariableOffsetBase = CON_ERR_DEVICE_VAR_OFFSET;
486     break;
487   }
488   ASSERT (ConsoleCheck != NULL);
489 
490   for (Index = 0; ((Index < ConsoleMenu->MenuNumber) && \
491        (Index < MAX_MENU_NUMBER)) ; Index++) {
492     CheckFlags = 0;
493     NewMenuEntry = BOpt_GetMenuEntry (ConsoleMenu, Index);
494     NewConsoleContext = (BM_CONSOLE_CONTEXT *) NewMenuEntry->VariableContext;
495     if (NewConsoleContext->IsActive) {
496       CheckFlags |= EFI_IFR_CHECKBOX_DEFAULT;
497       ConsoleCheck[Index] = TRUE;
498     } else {
499       ConsoleCheck[Index] = FALSE;
500     }
501     HiiCreateCheckBoxOpCode (
502       mStartOpCodeHandle,
503       (EFI_QUESTION_ID) (QuestionIdBase + Index),
504       VARSTORE_ID_BOOT_MAINT,
505       (UINT16) (VariableOffsetBase + Index),
506       NewMenuEntry->DisplayStringToken,
507       NewMenuEntry->HelpStringToken,
508       EFI_IFR_FLAG_CALLBACK,
509       CheckFlags,
510       NULL
511       );
512   }
513 
514   for (Index2 = 0; ((Index2 < TerminalMenu.MenuNumber) && \
515        (Index2 < MAX_MENU_NUMBER)); Index2++) {
516     CheckFlags          = 0;
517     NewMenuEntry        = BOpt_GetMenuEntry (&TerminalMenu, Index2);
518     NewTerminalContext  = (BM_TERMINAL_CONTEXT *) NewMenuEntry->VariableContext;
519 
520     ASSERT (Index < MAX_MENU_NUMBER);
521     if (((NewTerminalContext->IsConIn != 0) && (UpdatePageId == FORM_CON_IN_ID)) ||
522         ((NewTerminalContext->IsConOut != 0) && (UpdatePageId == FORM_CON_OUT_ID)) ||
523         ((NewTerminalContext->IsStdErr != 0) && (UpdatePageId == FORM_CON_ERR_ID))
524         ) {
525       CheckFlags |= EFI_IFR_CHECKBOX_DEFAULT;
526       ConsoleCheck[Index] = TRUE;
527     } else {
528       ConsoleCheck[Index] = FALSE;
529     }
530     HiiCreateCheckBoxOpCode (
531       mStartOpCodeHandle,
532       (EFI_QUESTION_ID) (QuestionIdBase + Index),
533       VARSTORE_ID_BOOT_MAINT,
534       (UINT16) (VariableOffsetBase + Index),
535       NewMenuEntry->DisplayStringToken,
536       NewMenuEntry->HelpStringToken,
537       EFI_IFR_FLAG_CALLBACK,
538       CheckFlags,
539       NULL
540       );
541 
542     Index++;
543   }
544 
545   UpdatePageEnd (CallbackData);
546 }
547 
548 /**
549   Update the page's NV Map if user has changed the order
550   a list. This list can be Boot Order or Driver Order.
551 
552   @param UpdatePageId    The form ID to be updated.
553   @param OptionMenu      The new list.
554   @param CallbackData    The BMM context data.
555 
556 **/
557 VOID
UpdateOrderPage(IN UINT16 UpdatePageId,IN BM_MENU_OPTION * OptionMenu,IN BMM_CALLBACK_DATA * CallbackData)558 UpdateOrderPage (
559   IN UINT16                           UpdatePageId,
560   IN BM_MENU_OPTION                   *OptionMenu,
561   IN BMM_CALLBACK_DATA                *CallbackData
562   )
563 {
564   BM_MENU_ENTRY     *NewMenuEntry;
565   UINT16            Index;
566   UINT16            OptionIndex;
567   VOID              *OptionsOpCodeHandle;
568   BOOLEAN           BootOptionFound;
569   UINT32            *OptionOrder;
570   EFI_QUESTION_ID   QuestionId;
571   UINT16            VarOffset;
572 
573   CallbackData->BmmAskSaveOrNot = TRUE;
574   UpdatePageStart (CallbackData);
575 
576   OptionOrder = NULL;
577   QuestionId = 0;
578   VarOffset = 0;
579   switch (UpdatePageId) {
580 
581   case FORM_BOOT_CHG_ID:
582     //
583     // If the BootOptionOrder in the BmmFakeNvData are same with the date in the BmmOldFakeNVData,
584     // means all Boot Options has been save in BootOptionMenu, we can get the date from the menu.
585     // else means browser maintains some uncommitted date which are not saved in BootOptionMenu,
586     // so we should not get the data from BootOptionMenu to show it.
587     //
588     if (CompareMem (CallbackData->BmmFakeNvData.BootOptionOrder, CallbackData->BmmOldFakeNVData.BootOptionOrder, sizeof (CallbackData->BmmFakeNvData.BootOptionOrder)) == 0) {
589       GetBootOrder (CallbackData);
590     }
591     OptionOrder = CallbackData->BmmFakeNvData.BootOptionOrder;
592     QuestionId = BOOT_OPTION_ORDER_QUESTION_ID;
593     VarOffset = BOOT_OPTION_ORDER_VAR_OFFSET;
594     break;
595 
596   case FORM_DRV_CHG_ID:
597     //
598     // If the DriverOptionOrder in the BmmFakeNvData are same with the date in the BmmOldFakeNVData,
599     // means all Driver Options has been save in DriverOptionMenu, we can get the DriverOptionOrder from the menu.
600     // else means browser maintains some uncommitted date which are not saved in DriverOptionMenu,
601     // so we should not get the data from DriverOptionMenu to show it.
602     //
603     if (CompareMem (CallbackData->BmmFakeNvData.DriverOptionOrder, CallbackData->BmmOldFakeNVData.DriverOptionOrder, sizeof (CallbackData->BmmFakeNvData.DriverOptionOrder)) == 0) {
604       GetDriverOrder (CallbackData);
605     }
606     OptionOrder = CallbackData->BmmFakeNvData.DriverOptionOrder;
607     QuestionId = DRIVER_OPTION_ORDER_QUESTION_ID;
608     VarOffset = DRIVER_OPTION_ORDER_VAR_OFFSET;
609     break;
610   }
611   ASSERT (OptionOrder != NULL);
612 
613   OptionsOpCodeHandle = HiiAllocateOpCodeHandle ();
614   ASSERT (OptionsOpCodeHandle != NULL);
615 
616   NewMenuEntry = NULL;
617   for (OptionIndex = 0; (OptionOrder[OptionIndex] != 0 && OptionIndex < MAX_MENU_NUMBER); OptionIndex++) {
618     BootOptionFound = FALSE;
619     for (Index = 0; Index < OptionMenu->MenuNumber; Index++) {
620       NewMenuEntry   = BOpt_GetMenuEntry (OptionMenu, Index);
621       if ((UINT32) (NewMenuEntry->OptionNumber + 1) == OptionOrder[OptionIndex]) {
622         BootOptionFound = TRUE;
623         break;
624       }
625     }
626     if (BootOptionFound) {
627       HiiCreateOneOfOptionOpCode (
628         OptionsOpCodeHandle,
629         NewMenuEntry->DisplayStringToken,
630         0,
631         EFI_IFR_TYPE_NUM_SIZE_32,
632         OptionOrder[OptionIndex]
633         );
634     }
635   }
636 
637   if (OptionMenu->MenuNumber > 0) {
638     HiiCreateOrderedListOpCode (
639       mStartOpCodeHandle,                          // Container for dynamic created opcodes
640       QuestionId,                                  // Question ID
641       VARSTORE_ID_BOOT_MAINT,                      // VarStore ID
642       VarOffset,                                   // Offset in Buffer Storage
643       STRING_TOKEN (STR_CHANGE_ORDER),             // Question prompt text
644       STRING_TOKEN (STR_CHANGE_ORDER),             // Question help text
645       0,                                           // Question flag
646       0,                                           // Ordered list flag, e.g. EFI_IFR_UNIQUE_SET
647       EFI_IFR_TYPE_NUM_SIZE_32,                    // Data type of Question value
648       100,                                         // Maximum container
649       OptionsOpCodeHandle,                         // Option Opcode list
650       NULL                                         // Default Opcode is NULL
651       );
652   }
653 
654   HiiFreeOpCodeHandle (OptionsOpCodeHandle);
655 
656   UpdatePageEnd (CallbackData);
657 
658 }
659 
660 /**
661   Refresh the text mode page.
662 
663   @param CallbackData    The BMM context data.
664 
665 **/
666 VOID
UpdateConModePage(IN BMM_CALLBACK_DATA * CallbackData)667 UpdateConModePage (
668   IN BMM_CALLBACK_DATA                *CallbackData
669   )
670 {
671   UINTN                         Mode;
672   UINTN                         Index;
673   UINTN                         Col;
674   UINTN                         Row;
675   CHAR16                        ModeString[50];
676   CHAR16                        *PStr;
677   UINTN                         MaxMode;
678   UINTN                         ValidMode;
679   EFI_STRING_ID                 *ModeToken;
680   EFI_STATUS                    Status;
681   VOID                          *OptionsOpCodeHandle;
682   EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL  *ConOut;
683 
684   ConOut    = gST->ConOut;
685   Index     = 0;
686   ValidMode = 0;
687   MaxMode   = (UINTN) (ConOut->Mode->MaxMode);
688 
689   CallbackData->BmmAskSaveOrNot = TRUE;
690 
691   UpdatePageStart (CallbackData);
692 
693   //
694   // Check valid mode
695   //
696   for (Mode = 0; Mode < MaxMode; Mode++) {
697     Status = ConOut->QueryMode (ConOut, Mode, &Col, &Row);
698     if (EFI_ERROR (Status)) {
699       continue;
700     }
701     ValidMode++;
702   }
703 
704   if (ValidMode == 0) {
705     return;
706   }
707 
708   OptionsOpCodeHandle = HiiAllocateOpCodeHandle ();
709   ASSERT (OptionsOpCodeHandle != NULL);
710 
711   ModeToken           = AllocateZeroPool (sizeof (EFI_STRING_ID) * ValidMode);
712   ASSERT(ModeToken != NULL);
713 
714   //
715   // Determin which mode should be the first entry in menu
716   //
717   GetConsoleOutMode (CallbackData);
718 
719   //
720   // Build text mode options
721   //
722   for (Mode = 0; Mode < MaxMode; Mode++) {
723     Status = ConOut->QueryMode (ConOut, Mode, &Col, &Row);
724     if (EFI_ERROR (Status)) {
725       continue;
726     }
727 
728     //
729     // Build mode string Column x Row
730     //
731     UnicodeValueToStringS (ModeString, sizeof (ModeString), 0, Col, 0);
732     PStr = &ModeString[0];
733     StrnCatS (PStr, ARRAY_SIZE (ModeString), L" x ", StrLen(L" x ") + 1);
734     PStr = PStr + StrLen (PStr);
735     UnicodeValueToStringS (
736       PStr,
737       sizeof (ModeString) - ((UINTN)PStr - (UINTN)&ModeString[0]),
738       0,
739       Row,
740       0
741       );
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
UpdateTerminalPage(IN BMM_CALLBACK_DATA * CallbackData)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
UpdateOptionPage(IN BMM_CALLBACK_DATA * CallbackData,IN EFI_FORM_ID FormId,IN EFI_DEVICE_PATH_PROTOCOL * DevicePath)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
UpdatePageBody(IN UINT16 UpdatePageId,IN BMM_CALLBACK_DATA * CallbackData)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
UpdatePageId(BMM_CALLBACK_DATA * Private,UINT16 NewPageId)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