69da6768e93ed7e65b7991ec261d554ca55d589c
[people/mcb30/edk2.git] / edk2 / EdkUnixPkg / Dxe / PlatformBds / Generic / BootMaint / BootMaint.c
1 /*++ \r
2 \r
3 Copyright (c) 2006, Intel Corporation                                                         \r
4 All rights reserved. This program and the accompanying materials                          \r
5 are licensed and made available under the terms and conditions of the BSD License         \r
6 which accompanies this distribution.  The full text of the license may be found at        \r
7 http://opensource.org/licenses/bsd-license.php                                            \r
8                                                                                           \r
9 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,                     \r
10 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.             \r
11 \r
12 Module Name:\r
13 \r
14   BootMaint.c\r
15     \r
16 Abstract:\r
17 \r
18   Boot Maintainence Main File\r
19 \r
20 --*/\r
21 \r
22 #include "Generic/Bds.h"\r
23 #include "BootMaint.h"\r
24 #include "BdsStrDefs.h"\r
25 #include "FormGuid.h"\r
26 \r
27 //\r
28 // Form binary for Boot Maintenance\r
29 //\r
30 extern UINT8    BmBin[];\r
31 extern UINT8    FEBin[];\r
32 extern EFI_GUID gBdsStringPackGuid;\r
33 extern BOOLEAN  gConnectAllHappened;\r
34 \r
35 EFI_GUID        EfiLegacyDevOrderGuid = EFI_LEGACY_DEV_ORDER_VARIABLE_GUID;\r
36 \r
37 VOID\r
38 InitAllMenu (\r
39   IN  BMM_CALLBACK_DATA    *CallbackData\r
40   );\r
41 \r
42 VOID\r
43 FreeAllMenu (\r
44   VOID\r
45   );\r
46 \r
47 EFI_STATUS\r
48 CreateMenuStringToken (\r
49   IN BMM_CALLBACK_DATA                *CallbackData,\r
50   IN EFI_HII_HANDLE                   HiiHandle,\r
51   IN BM_MENU_OPTION                   *MenuOption\r
52   )\r
53 /*++\r
54 Routine Description:\r
55 \r
56   Create string tokens for a menu from its help strings and display strings\r
57 \r
58 Arguments:\r
59 \r
60   HiiHandle       - Hii Handle of the package to be updated.\r
61   \r
62   MenuOption      - The Menu whose string tokens need to be created\r
63 \r
64 Returns:\r
65 \r
66   EFI_SUCCESS     - string tokens created successfully\r
67   \r
68   others          - contain some errors\r
69   \r
70 --*/\r
71 {\r
72   BM_MENU_ENTRY *NewMenuEntry;\r
73   UINTN         Index;\r
74 \r
75   for (Index = 0; Index < MenuOption->MenuNumber; Index++) {\r
76     NewMenuEntry = BOpt_GetMenuEntry (MenuOption, Index);\r
77     CallbackData->Hii->NewString (\r
78                         CallbackData->Hii,\r
79                         NULL,\r
80                         HiiHandle,\r
81                         &NewMenuEntry->DisplayStringToken,\r
82                         NewMenuEntry->DisplayString\r
83                         );\r
84 \r
85     if (NULL == NewMenuEntry->HelpString) {\r
86       NewMenuEntry->HelpStringToken = NewMenuEntry->DisplayStringToken;\r
87     } else {\r
88       CallbackData->Hii->NewString (\r
89                           CallbackData->Hii,\r
90                           NULL,\r
91                           HiiHandle,\r
92                           &NewMenuEntry->HelpStringToken,\r
93                           NewMenuEntry->HelpString\r
94                           );\r
95     }\r
96   }\r
97 \r
98   return EFI_SUCCESS;\r
99 }\r
100 \r
101 EFI_STATUS\r
102 EFIAPI\r
103 DriverCallback (\r
104   IN EFI_FORM_CALLBACK_PROTOCOL       *This,\r
105   IN UINT16                           KeyValue,\r
106   IN EFI_IFR_DATA_ARRAY               *Data,\r
107   OUT EFI_HII_CALLBACK_PACKET         **Packet\r
108   )\r
109 /*++\r
110 Routine Description:\r
111 \r
112   Callback Function for boot maintenance utility user interface interaction.\r
113 \r
114 Arguments:\r
115 \r
116   This            - File explorer callback protocol pointer.     \r
117   KeyValue        - Key value to identify the type of data to expect.\r
118   Data            - A pointer to the data being sent to the original exporting driver.\r
119   Packet          - A pointer to a packet of information which a driver passes back to the browser.\r
120 \r
121 Returns:\r
122 \r
123   EFI_SUCCESS     - Callback ended successfully.\r
124   Others          - Contain some errors.\r
125   \r
126 --*/\r
127 {\r
128   BMM_CALLBACK_DATA *Private;\r
129   BM_MENU_ENTRY     *NewMenuEntry;\r
130   BMM_FAKE_NV_DATA  *CurrentFakeNVMap;\r
131   EFI_STATUS        Status;\r
132   UINTN             OldValue;\r
133   UINTN             NewValue;\r
134   UINTN             Number;\r
135   UINTN             Pos;\r
136   UINTN             Bit;\r
137   UINT16            NewValuePos;\r
138   UINT16            Index2;\r
139   UINT16            Index;\r
140   UINT8             *OldLegacyDev;\r
141   UINT8             *NewLegacyDev;\r
142   UINT8             *Location;\r
143   UINT8             *DisMap;\r
144   FORM_ID           FormId;\r
145 \r
146   OldValue                        = 0;\r
147   NewValue                        = 0;\r
148   Number                          = 0;\r
149   OldLegacyDev                    = NULL;\r
150   NewLegacyDev                    = NULL;\r
151   NewValuePos                     = 0;\r
152   DisMap                          = NULL;\r
153 \r
154   Private                         = BMM_CALLBACK_DATA_FROM_THIS (This);\r
155   UpdateData->FormCallbackHandle  = (EFI_PHYSICAL_ADDRESS) (UINTN) Private->BmmCallbackHandle;\r
156   CurrentFakeNVMap                = (BMM_FAKE_NV_DATA *) Data->NvRamMap;\r
157   Private->BmmFakeNvData          = CurrentFakeNVMap;\r
158   Location                        = (UINT8 *) &UpdateData->Data;\r
159 \r
160   UpdatePageId (Private, KeyValue);\r
161 \r
162   //\r
163   // need to be subtituded.\r
164   //\r
165   // Update Select FD/HD/CD/NET/BEV Order Form\r
166   //\r
167   if (FORM_SET_FD_ORDER_ID == Private->BmmPreviousPageId ||\r
168       FORM_SET_HD_ORDER_ID == Private->BmmPreviousPageId ||\r
169       FORM_SET_CD_ORDER_ID == Private->BmmPreviousPageId ||\r
170       FORM_SET_NET_ORDER_ID == Private->BmmPreviousPageId ||\r
171       FORM_SET_BEV_ORDER_ID == Private->BmmPreviousPageId ||\r
172       ((FORM_BOOT_SETUP_ID == Private->BmmPreviousPageId) &&\r
173       (KeyValue >= LEGACY_FD_QUESTION_ID) &&\r
174        (KeyValue < (LEGACY_BEV_QUESTION_ID + 100)) )\r
175       ) {\r
176 \r
177     DisMap  = Private->BmmOldFakeNVData.DisableMap;\r
178 \r
179     FormId  = Private->BmmPreviousPageId;\r
180     if (FormId == FORM_BOOT_SETUP_ID) {\r
181       FormId = Private->BmmCurrentPageId;\r
182     }\r
183 \r
184     switch (FormId) {\r
185     case FORM_SET_FD_ORDER_ID:\r
186       Number        = (UINT16) LegacyFDMenu.MenuNumber;\r
187       OldLegacyDev  = Private->BmmOldFakeNVData.LegacyFD;\r
188       NewLegacyDev  = CurrentFakeNVMap->LegacyFD;\r
189       break;\r
190 \r
191     case FORM_SET_HD_ORDER_ID:\r
192       Number        = (UINT16) LegacyHDMenu.MenuNumber;\r
193       OldLegacyDev  = Private->BmmOldFakeNVData.LegacyHD;\r
194       NewLegacyDev  = CurrentFakeNVMap->LegacyHD;\r
195       break;\r
196 \r
197     case FORM_SET_CD_ORDER_ID:\r
198       Number        = (UINT16) LegacyCDMenu.MenuNumber;\r
199       OldLegacyDev  = Private->BmmOldFakeNVData.LegacyCD;\r
200       NewLegacyDev  = CurrentFakeNVMap->LegacyCD;\r
201       break;\r
202 \r
203     case FORM_SET_NET_ORDER_ID:\r
204       Number        = (UINT16) LegacyNETMenu.MenuNumber;\r
205       OldLegacyDev  = Private->BmmOldFakeNVData.LegacyNET;\r
206       NewLegacyDev  = CurrentFakeNVMap->LegacyNET;\r
207       break;\r
208 \r
209     case FORM_SET_BEV_ORDER_ID:\r
210       Number        = (UINT16) LegacyBEVMenu.MenuNumber;\r
211       OldLegacyDev  = Private->BmmOldFakeNVData.LegacyBEV;\r
212       NewLegacyDev  = CurrentFakeNVMap->LegacyBEV;\r
213       break;\r
214 \r
215     default:\r
216       break;\r
217     }\r
218     //\r
219     //  First, find the different position\r
220     //  if there is change, it should be only one\r
221     //\r
222     for (Index = 0; Index < Number; Index++) {\r
223       if (OldLegacyDev[Index] != NewLegacyDev[Index]) {\r
224         OldValue  = OldLegacyDev[Index];\r
225         NewValue  = NewLegacyDev[Index];\r
226         break;\r
227       }\r
228     }\r
229 \r
230     if (Index != Number) {\r
231       //\r
232       // there is change, now process\r
233       //\r
234       if (0xFF == NewValue) {\r
235         //\r
236         // This item will be disable\r
237         // Just move the items behind this forward to overlap it\r
238         //\r
239         Pos = OldValue / 8;\r
240         Bit = 7 - (OldValue % 8);\r
241         DisMap[Pos] |= (UINT8) (1 << Bit);\r
242         for (Index2 = Index; Index2 < Number - 1; Index2++) {\r
243           NewLegacyDev[Index2] = NewLegacyDev[Index2 + 1];\r
244         }\r
245 \r
246         NewLegacyDev[Index2] = 0xFF;\r
247       } else {\r
248         for (Index2 = 0; Index2 < Number; Index2++) {\r
249           if (Index2 == Index) {\r
250             continue;\r
251           }\r
252 \r
253           if (OldLegacyDev[Index2] == NewValue) {\r
254             //\r
255             // If NewValue is in OldLegacyDev array\r
256             // remember its old position\r
257             //\r
258             NewValuePos = Index2;\r
259             break;\r
260           }\r
261         }\r
262 \r
263         if (Index2 != Number) {\r
264           //\r
265           // We will change current item to an existing item\r
266           // (It's hard to describe here, please read code, it's like a cycle-moving)\r
267           //\r
268           for (Index2 = NewValuePos; Index2 != Index;) {\r
269             if (NewValuePos < Index) {\r
270               NewLegacyDev[Index2] = OldLegacyDev[Index2 + 1];\r
271               Index2++;\r
272             } else {\r
273               NewLegacyDev[Index2] = OldLegacyDev[Index2 - 1];\r
274               Index2--;\r
275             }\r
276           }\r
277         } else {\r
278           //\r
279           // If NewValue is not in OldlegacyDev array, we are changing to a disabled item\r
280           // so we should modify DisMap to reflect the change\r
281           //\r
282           Pos = NewValue / 8;\r
283           Bit = 7 - (NewValue % 8);\r
284           DisMap[Pos] &= ~ (UINT8) (1 << Bit);\r
285           if (0xFF != OldValue) {\r
286             //\r
287             // Because NewValue is a item that was disabled before\r
288             // so after changing the OldValue should be disabled\r
289             // actually we are doing a swap of enable-disable states of two items\r
290             //\r
291             Pos = OldValue / 8;\r
292             Bit = 7 - (OldValue % 8);\r
293             DisMap[Pos] |= (UINT8) (1 << Bit);\r
294           }\r
295         }\r
296       }\r
297       //\r
298       // To prevent DISABLE appears in the middle of the list\r
299       // we should perform a re-ordering\r
300       //\r
301       Index = 0;\r
302       while (Index < Number) {\r
303         if (0xFF != NewLegacyDev[Index]) {\r
304           Index++;\r
305           continue;\r
306         }\r
307 \r
308         Index2 = Index;\r
309         Index2++;\r
310         while (Index2 < Number) {\r
311           if (0xFF != NewLegacyDev[Index2]) {\r
312             break;\r
313           }\r
314 \r
315           Index2++;\r
316         }\r
317 \r
318         if (Index2 < Number) {\r
319           NewLegacyDev[Index]   = NewLegacyDev[Index2];\r
320           NewLegacyDev[Index2]  = 0xFF;\r
321         }\r
322 \r
323         Index++;\r
324       }\r
325 \r
326       CopyMem (\r
327         OldLegacyDev,\r
328         NewLegacyDev,\r
329         Number\r
330         );\r
331     }\r
332   }\r
333 \r
334   if (KeyValue < FILE_OPTION_OFFSET) {\r
335     if (KeyValue < NORMAL_GOTO_OFFSET) {\r
336       switch (KeyValue) {\r
337       case KEY_VALUE_BOOT_FROM_FILE:\r
338         Private->FeCurrentState = BOOT_FROM_FILE_STATE;\r
339 \r
340         //\r
341         // Exit Bmm main formset to send File Explorer formset.\r
342         //\r
343         CreateCallbackPacket (Packet, EXIT_REQUIRED);\r
344 \r
345         break;\r
346 \r
347       case FORM_BOOT_ADD_ID:\r
348         Private->FeCurrentState = ADD_BOOT_OPTION_STATE;\r
349 \r
350         //\r
351         // Exit Bmm main formset to send File Explorer formset.\r
352         //\r
353         CreateCallbackPacket (Packet, EXIT_REQUIRED);\r
354         break;\r
355 \r
356       case FORM_DRV_ADD_FILE_ID:\r
357         Private->FeCurrentState = ADD_DRIVER_OPTION_STATE;\r
358 \r
359         //\r
360         // Exit Bmm main formset to send File Explorer formset.\r
361         //\r
362         CreateCallbackPacket (Packet, EXIT_REQUIRED);\r
363 \r
364         break;\r
365 \r
366       case FORM_DRV_ADD_HANDLE_ID:\r
367         CleanUpPage (FORM_DRV_ADD_HANDLE_ID, Private);\r
368         UpdateDrvAddHandlePage (Private);\r
369         break;\r
370 \r
371       case FORM_BOOT_DEL_ID:\r
372         CleanUpPage (FORM_BOOT_DEL_ID, Private);\r
373         UpdateBootDelPage (Private);\r
374         break;\r
375 \r
376       case FORM_BOOT_CHG_ID:\r
377       case FORM_DRV_CHG_ID:\r
378         UpdatePageBody (KeyValue, Private);\r
379         break;\r
380 \r
381       case FORM_DRV_DEL_ID:\r
382         CleanUpPage (FORM_DRV_DEL_ID, Private);\r
383         UpdateDrvDelPage (Private);\r
384         break;\r
385 \r
386       case FORM_BOOT_NEXT_ID:\r
387         CleanUpPage (FORM_BOOT_NEXT_ID, Private);\r
388         UpdateBootNextPage (Private);\r
389         break;\r
390 \r
391       case FORM_TIME_OUT_ID:\r
392         CleanUpPage (FORM_TIME_OUT_ID, Private);\r
393         UpdateTimeOutPage (Private);\r
394         break;\r
395 \r
396       case FORM_RESET:\r
397         gRT->ResetSystem (EfiResetCold, EFI_SUCCESS, 0, NULL);\r
398         return EFI_UNSUPPORTED;\r
399 \r
400       case FORM_CON_IN_ID:\r
401       case FORM_CON_OUT_ID:\r
402       case FORM_CON_ERR_ID:\r
403         UpdatePageBody (KeyValue, Private);\r
404         break;\r
405 \r
406       case FORM_CON_COM_ID:\r
407         CleanUpPage (FORM_CON_COM_ID, Private);\r
408         UpdateConCOMPage (Private);\r
409         break;\r
410 \r
411       case FORM_SET_FD_ORDER_ID:\r
412       case FORM_SET_HD_ORDER_ID:\r
413       case FORM_SET_CD_ORDER_ID:\r
414       case FORM_SET_NET_ORDER_ID:\r
415       case FORM_SET_BEV_ORDER_ID:\r
416         CleanUpPage (KeyValue, Private);\r
417         UpdateSetLegacyDeviceOrderPage (KeyValue, Private);\r
418         break;\r
419 \r
420       case KEY_VALUE_SAVE_AND_EXIT:\r
421       case KEY_VALUE_NO_SAVE_AND_EXIT:\r
422 \r
423         if (KeyValue == KEY_VALUE_SAVE_AND_EXIT) {\r
424           Status = ApplyChangeHandler (Private, CurrentFakeNVMap, Private->BmmPreviousPageId);\r
425           if (EFI_ERROR (Status)) {\r
426             return Status;\r
427           }\r
428         } else if (KeyValue == KEY_VALUE_NO_SAVE_AND_EXIT) {\r
429           DiscardChangeHandler (Private, CurrentFakeNVMap);\r
430         }\r
431         //\r
432         // Tell browser not to ask for confirmation of changes,\r
433         // since we have already applied or discarded.\r
434         //\r
435         CreateCallbackPacket (Packet, NV_NOT_CHANGED);\r
436         break;\r
437 \r
438       default:\r
439         break;\r
440       }\r
441     } else if ((KeyValue >= TERMINAL_OPTION_OFFSET) && (KeyValue < CONSOLE_OPTION_OFFSET)) {\r
442       Index2                    = (UINT16) (KeyValue - TERMINAL_OPTION_OFFSET);\r
443       Private->CurrentTerminal  = Index2;\r
444 \r
445       CleanUpPage (FORM_CON_COM_SETUP_ID, Private);\r
446       UpdateTerminalPage (Private);\r
447 \r
448     } else if (KeyValue >= HANDLE_OPTION_OFFSET) {\r
449       Index2                  = (UINT16) (KeyValue - HANDLE_OPTION_OFFSET);\r
450 \r
451       NewMenuEntry            = BOpt_GetMenuEntry (&DriverMenu, Index2);\r
452       ASSERT (NewMenuEntry != NULL);\r
453       Private->HandleContext  = (BM_HANDLE_CONTEXT *) NewMenuEntry->VariableContext;\r
454 \r
455       CleanUpPage (FORM_DRV_ADD_HANDLE_DESC_ID, Private);\r
456 \r
457       Private->MenuEntry                  = NewMenuEntry;\r
458       Private->LoadContext->FilePathList  = Private->HandleContext->DevicePath;\r
459 \r
460       UpdateDriverAddHandleDescPage (Private);\r
461     }\r
462   }\r
463 \r
464   return EFI_SUCCESS;\r
465 }\r
466 \r
467 EFI_STATUS\r
468 ApplyChangeHandler (\r
469   IN  BMM_CALLBACK_DATA               *Private,\r
470   IN  BMM_FAKE_NV_DATA                *CurrentFakeNVMap,\r
471   IN  FORM_ID                         FormId\r
472   )\r
473 /*++\r
474 \r
475 Routine Description:\r
476 \r
477   Function handling request to apply changes for BMM pages.\r
478 \r
479 Arguments:\r
480 \r
481   Private          - Pointer to callback data buffer.\r
482   CurrentFakeNVMap - Pointer to buffer holding data of various values used by BMM\r
483   FormId           - ID of the form which has sent the request to apply change.\r
484 \r
485 Returns:\r
486 \r
487   EFI_SUCCESS      - Change successfully applied.\r
488   Other            - Error occurs while trying to apply changes.\r
489 \r
490 --*/\r
491 {\r
492   BM_CONSOLE_CONTEXT  *NewConsoleContext;\r
493   BM_TERMINAL_CONTEXT *NewTerminalContext;\r
494   BM_LOAD_CONTEXT     *NewLoadContext;\r
495   BM_MENU_ENTRY       *NewMenuEntry;\r
496   EFI_STATUS          Status;\r
497   UINT16              Index;\r
498 \r
499   Status = EFI_SUCCESS;\r
500 \r
501   switch (FormId) {\r
502   case FORM_SET_FD_ORDER_ID:\r
503   case FORM_SET_HD_ORDER_ID:\r
504   case FORM_SET_CD_ORDER_ID:\r
505   case FORM_SET_NET_ORDER_ID:\r
506   case FORM_SET_BEV_ORDER_ID:\r
507     Var_UpdateBBSOption (Private);\r
508     break;\r
509 \r
510   case FORM_BOOT_DEL_ID:\r
511     for (Index = 0; Index < BootOptionMenu.MenuNumber; Index++) {\r
512       NewMenuEntry            = BOpt_GetMenuEntry (&BootOptionMenu, Index);\r
513       NewLoadContext          = (BM_LOAD_CONTEXT *) NewMenuEntry->VariableContext;\r
514       NewLoadContext->Deleted = CurrentFakeNVMap->BootOptionDel[Index];\r
515     }\r
516 \r
517     Var_DelBootOption ();\r
518     break;\r
519 \r
520   case FORM_DRV_DEL_ID:\r
521     for (Index = 0; Index < DriverOptionMenu.MenuNumber; Index++) {\r
522       NewMenuEntry            = BOpt_GetMenuEntry (&DriverOptionMenu, Index);\r
523       NewLoadContext          = (BM_LOAD_CONTEXT *) NewMenuEntry->VariableContext;\r
524       NewLoadContext->Deleted = CurrentFakeNVMap->DriverOptionDel[Index];\r
525     }\r
526 \r
527     Var_DelDriverOption ();\r
528     break;\r
529 \r
530   case FORM_BOOT_CHG_ID:\r
531     Status = Var_UpdateBootOrder (Private);\r
532     break;\r
533 \r
534   case FORM_DRV_CHG_ID:\r
535     Status = Var_UpdateDriverOrder (Private);\r
536     break;\r
537 \r
538   case FORM_TIME_OUT_ID:\r
539     Status = gRT->SetVariable (\r
540                     L"Timeout",\r
541                     &gEfiGlobalVariableGuid,\r
542                     VAR_FLAG,\r
543                     sizeof (UINT16),\r
544                     &(CurrentFakeNVMap->BootTimeOut)\r
545                     );\r
546     if (EFI_ERROR (Status)) {\r
547       goto Error;\r
548     }\r
549 \r
550     Private->BmmOldFakeNVData.BootTimeOut = CurrentFakeNVMap->BootTimeOut;\r
551     break;\r
552 \r
553   case FORM_BOOT_NEXT_ID:\r
554     Status = Var_UpdateBootNext (Private);\r
555     break;\r
556 \r
557   case FORM_CON_COM_ID:\r
558     NewMenuEntry                      = BOpt_GetMenuEntry (&TerminalMenu, Private->CurrentTerminal);\r
559 \r
560     ASSERT (NewMenuEntry != NULL);\r
561 \r
562     NewTerminalContext                = (BM_TERMINAL_CONTEXT *) NewMenuEntry->VariableContext;\r
563 \r
564     NewTerminalContext->BaudRateIndex = CurrentFakeNVMap->COMBaudRate;\r
565     NewTerminalContext->BaudRate      = BaudRateList[CurrentFakeNVMap->COMBaudRate].Value;\r
566     NewTerminalContext->DataBitsIndex = CurrentFakeNVMap->COMDataRate;\r
567     NewTerminalContext->DataBits      = (UINT8) DataBitsList[CurrentFakeNVMap->COMDataRate].Value;\r
568     NewTerminalContext->StopBitsIndex = CurrentFakeNVMap->COMStopBits;\r
569     NewTerminalContext->StopBits      = (UINT8) StopBitsList[CurrentFakeNVMap->COMStopBits].Value;\r
570     NewTerminalContext->ParityIndex   = CurrentFakeNVMap->COMParity;\r
571     NewTerminalContext->Parity        = (UINT8) ParityList[CurrentFakeNVMap->COMParity].Value;\r
572     NewTerminalContext->TerminalType  = CurrentFakeNVMap->COMTerminalType;\r
573 \r
574     ChangeTerminalDevicePath (\r
575       NewTerminalContext->DevicePath,\r
576       FALSE\r
577       );\r
578 \r
579     Var_UpdateConsoleInpOption ();\r
580     Var_UpdateConsoleOutOption ();\r
581     Var_UpdateErrorOutOption ();\r
582     break;\r
583 \r
584   case FORM_CON_IN_ID:\r
585     for (Index = 0; Index < ConsoleInpMenu.MenuNumber; Index++) {\r
586       NewMenuEntry                = BOpt_GetMenuEntry (&ConsoleInpMenu, Index);\r
587       NewConsoleContext           = (BM_CONSOLE_CONTEXT *) NewMenuEntry->VariableContext;\r
588       NewConsoleContext->IsActive = CurrentFakeNVMap->ConsoleCheck[Index];\r
589     }\r
590 \r
591     for (Index = 0; Index < TerminalMenu.MenuNumber; Index++) {\r
592       NewMenuEntry                = BOpt_GetMenuEntry (&TerminalMenu, Index);\r
593       NewTerminalContext          = (BM_TERMINAL_CONTEXT *) NewMenuEntry->VariableContext;\r
594       NewTerminalContext->IsConIn = CurrentFakeNVMap->ConsoleCheck[Index + ConsoleInpMenu.MenuNumber];\r
595     }\r
596 \r
597     Var_UpdateConsoleInpOption ();\r
598     break;\r
599 \r
600   case FORM_CON_OUT_ID:\r
601     for (Index = 0; Index < ConsoleOutMenu.MenuNumber; Index++) {\r
602       NewMenuEntry                = BOpt_GetMenuEntry (&ConsoleOutMenu, Index);\r
603       NewConsoleContext           = (BM_CONSOLE_CONTEXT *) NewMenuEntry->VariableContext;\r
604       NewConsoleContext->IsActive = CurrentFakeNVMap->ConsoleCheck[Index];\r
605     }\r
606 \r
607     for (Index = 0; Index < TerminalMenu.MenuNumber; Index++) {\r
608       NewMenuEntry                  = BOpt_GetMenuEntry (&TerminalMenu, Index);\r
609       NewTerminalContext            = (BM_TERMINAL_CONTEXT *) NewMenuEntry->VariableContext;\r
610       NewTerminalContext->IsConOut  = CurrentFakeNVMap->ConsoleCheck[Index + ConsoleOutMenu.MenuNumber];\r
611     }\r
612 \r
613     Var_UpdateConsoleOutOption ();\r
614     break;\r
615 \r
616   case FORM_CON_ERR_ID:\r
617     for (Index = 0; Index < ConsoleErrMenu.MenuNumber; Index++) {\r
618       NewMenuEntry                = BOpt_GetMenuEntry (&ConsoleErrMenu, Index);\r
619       NewConsoleContext           = (BM_CONSOLE_CONTEXT *) NewMenuEntry->VariableContext;\r
620       NewConsoleContext->IsActive = CurrentFakeNVMap->ConsoleCheck[Index];\r
621     }\r
622 \r
623     for (Index = 0; Index < TerminalMenu.MenuNumber; Index++) {\r
624       NewMenuEntry                  = BOpt_GetMenuEntry (&TerminalMenu, Index);\r
625       NewTerminalContext            = (BM_TERMINAL_CONTEXT *) NewMenuEntry->VariableContext;\r
626       NewTerminalContext->IsStdErr  = CurrentFakeNVMap->ConsoleCheck[Index + ConsoleErrMenu.MenuNumber];\r
627     }\r
628 \r
629     Var_UpdateErrorOutOption ();\r
630     break;\r
631 \r
632   case FORM_DRV_ADD_HANDLE_DESC_ID:\r
633     Status = Var_UpdateDriverOption (\r
634                Private,\r
635                Private->BmmHiiHandle,\r
636                CurrentFakeNVMap->DriverAddHandleDesc,\r
637                CurrentFakeNVMap->DriverAddHandleOptionalData,\r
638                CurrentFakeNVMap->DriverAddForceReconnect\r
639                );\r
640     if (EFI_ERROR (Status)) {\r
641       goto Error;\r
642     }\r
643 \r
644     BOpt_GetDriverOptions (Private);\r
645     CreateMenuStringToken (Private, Private->BmmHiiHandle, &DriverOptionMenu);\r
646     break;\r
647 \r
648   default:\r
649     break;\r
650   }\r
651 \r
652 Error:\r
653   return Status;\r
654 }\r
655 \r
656 VOID\r
657 DiscardChangeHandler (\r
658   IN  BMM_CALLBACK_DATA               *Private,\r
659   IN  BMM_FAKE_NV_DATA                *CurrentFakeNVMap\r
660   )\r
661 {\r
662   UINT16  Index;\r
663 \r
664   switch (Private->BmmPreviousPageId) {\r
665   case FORM_BOOT_CHG_ID:\r
666   case FORM_DRV_CHG_ID:\r
667     CopyMem (CurrentFakeNVMap->OptionOrder, Private->BmmOldFakeNVData.OptionOrder, 100);\r
668     break;\r
669 \r
670   case FORM_BOOT_DEL_ID:\r
671     for (Index = 0; Index < BootOptionMenu.MenuNumber; Index++) {\r
672       CurrentFakeNVMap->BootOptionDel[Index] = 0x00;\r
673     }\r
674     break;\r
675 \r
676   case FORM_DRV_DEL_ID:\r
677     for (Index = 0; Index < DriverOptionMenu.MenuNumber; Index++) {\r
678       CurrentFakeNVMap->DriverOptionDel[Index] = 0x00;\r
679     }\r
680     break;\r
681 \r
682   case FORM_BOOT_NEXT_ID:\r
683     CurrentFakeNVMap->BootNext = Private->BmmOldFakeNVData.BootNext;\r
684     break;\r
685 \r
686   case FORM_TIME_OUT_ID:\r
687     CurrentFakeNVMap->BootTimeOut = Private->BmmOldFakeNVData.BootTimeOut;\r
688     break;\r
689 \r
690   case FORM_DRV_ADD_HANDLE_DESC_ID:\r
691   case FORM_DRV_ADD_FILE_ID:\r
692   case FORM_DRV_ADD_HANDLE_ID:\r
693     CurrentFakeNVMap->DriverAddHandleDesc[0]          = 0x0000;\r
694     CurrentFakeNVMap->DriverAddHandleOptionalData[0]  = 0x0000;\r
695     break;\r
696 \r
697   default:\r
698     break;\r
699   }\r
700 }\r
701 \r
702 EFI_STATUS\r
703 EFIAPI\r
704 NvWrite (\r
705   IN     EFI_FORM_CALLBACK_PROTOCOL              *This,\r
706   IN     CHAR16                                  *VariableName,\r
707   IN     EFI_GUID                                *VendorGuid,\r
708   OUT    UINT32                                  Attributes OPTIONAL,\r
709   IN OUT UINTN                                   DataSize,\r
710   OUT    VOID                                    *Buffer,\r
711   OUT    BOOLEAN                                 *ResetRequired\r
712   )\r
713 {\r
714   //\r
715   // Do nothing here. Just to catch the F10, we use "Apply Changes" tag to save.\r
716   //\r
717   return EFI_SUCCESS;\r
718 }\r
719 \r
720 EFI_STATUS\r
721 InitializeBM (\r
722   VOID\r
723   )\r
724 /*++\r
725 Routine Description:\r
726 \r
727   Initialize the Boot Maintenance Utitliy\r
728 \r
729 Arguments:\r
730 \r
731   ImageHandle     - caller provided handle\r
732   \r
733   SystemTable     - caller provided system tables\r
734 \r
735 Returns:\r
736 \r
737   EFI_SUCCESS     - utility ended successfully\r
738   \r
739   others          - contain some errors\r
740   \r
741 --*/\r
742 {\r
743   EFI_LEGACY_BIOS_PROTOCOL  *LegacyBios;\r
744   EFI_HII_PACKAGES          *PackageList;\r
745   BMM_CALLBACK_DATA         *BmmCallbackInfo;\r
746   EFI_HII_PROTOCOL          *Hii;\r
747   EFI_HII_HANDLE            HiiHandle;\r
748   EFI_STATUS                Status;\r
749   EFI_HANDLE                Handle;\r
750   UINT8                     *Ptr;\r
751   UINT8                     *Location;\r
752 \r
753   Status      = EFI_SUCCESS;\r
754   UpdateData  = NULL;\r
755   //\r
756   // Initialize EfiUtilityLib and EfiDriverLib\r
757   // Since many functions in UtilityLib must be used and\r
758   // SetupBrowser use DriverLib\r
759   //\r
760   //\r
761   // There should be only one EFI_HII_PROTOCOL Image\r
762   //\r
763   Status = EfiLibLocateProtocol (&gEfiHiiProtocolGuid, (VOID**)&Hii);\r
764   if (EFI_ERROR (Status)) {\r
765     return Status;\r
766   }\r
767   //\r
768   // Create CallbackData structures for Driver Callback\r
769   //\r
770   BmmCallbackInfo = AllocateZeroPool (sizeof (BMM_CALLBACK_DATA));\r
771   if (!BmmCallbackInfo) {\r
772     return EFI_OUT_OF_RESOURCES;\r
773   }\r
774   //\r
775   // Create LoadOption in BmmCallbackInfo for Driver Callback\r
776   //\r
777   Ptr = AllocateZeroPool (sizeof (BM_LOAD_CONTEXT) + sizeof (BM_FILE_CONTEXT) + sizeof (BM_HANDLE_CONTEXT) + sizeof (BM_MENU_ENTRY));\r
778   if (!Ptr) {\r
779     SafeFreePool (BmmCallbackInfo);\r
780     return EFI_OUT_OF_RESOURCES;\r
781   }\r
782   //\r
783   // Initialize Bmm callback data.\r
784   //\r
785   BmmCallbackInfo->LoadContext = (BM_LOAD_CONTEXT *) Ptr;\r
786   Ptr += sizeof (BM_LOAD_CONTEXT);\r
787 \r
788   BmmCallbackInfo->FileContext = (BM_FILE_CONTEXT *) Ptr;\r
789   Ptr += sizeof (BM_FILE_CONTEXT);\r
790 \r
791   BmmCallbackInfo->HandleContext = (BM_HANDLE_CONTEXT *) Ptr;\r
792   Ptr += sizeof (BM_HANDLE_CONTEXT);\r
793 \r
794   BmmCallbackInfo->MenuEntry      = (BM_MENU_ENTRY *) Ptr;\r
795 \r
796   BmmCallbackInfo->BmmFakeNvData  = &BmmCallbackInfo->BmmOldFakeNVData;\r
797 \r
798   ZeroMem (BmmCallbackInfo->BmmFakeNvData, sizeof (BMM_FAKE_NV_DATA));\r
799 \r
800   BmmCallbackInfo->Signature                  = BMM_CALLBACK_DATA_SIGNATURE;\r
801   BmmCallbackInfo->Hii                        = Hii;\r
802   BmmCallbackInfo->BmmDriverCallback.NvRead   = NULL;\r
803   BmmCallbackInfo->BmmDriverCallback.NvWrite  = NvWrite;\r
804   BmmCallbackInfo->BmmDriverCallback.Callback = DriverCallback;\r
805   BmmCallbackInfo->BmmPreviousPageId          = FORM_MAIN_ID;\r
806   BmmCallbackInfo->BmmCurrentPageId           = FORM_MAIN_ID;\r
807   BmmCallbackInfo->FeDriverCallback.NvRead    = NULL;\r
808   BmmCallbackInfo->FeDriverCallback.NvWrite   = NvWrite;\r
809   BmmCallbackInfo->FeDriverCallback.Callback  = FileExplorerCallback;\r
810   BmmCallbackInfo->FeCurrentState             = INACTIVE_STATE;\r
811   BmmCallbackInfo->FeDisplayContext           = UNKNOWN_CONTEXT;\r
812 \r
813   //\r
814   // Install bmm callback protocol interface\r
815   //\r
816   Handle = NULL;\r
817   Status = gBS->InstallProtocolInterface (\r
818                   &Handle,\r
819                   &gEfiFormCallbackProtocolGuid,\r
820                   EFI_NATIVE_INTERFACE,\r
821                   &BmmCallbackInfo->BmmDriverCallback\r
822                   );\r
823 \r
824   if (EFI_ERROR (Status)) {\r
825     return Status;\r
826   }\r
827 \r
828   BmmCallbackInfo->BmmCallbackHandle = Handle;\r
829 \r
830   //\r
831   // Install file explorer callback protocol interface\r
832   //\r
833   Handle = NULL;\r
834   Status = gBS->InstallProtocolInterface (\r
835                   &Handle,\r
836                   &gEfiFormCallbackProtocolGuid,\r
837                   EFI_NATIVE_INTERFACE,\r
838                   &BmmCallbackInfo->FeDriverCallback\r
839                   );\r
840 \r
841   if (EFI_ERROR (Status)) {\r
842     return Status;\r
843   }\r
844 \r
845   BmmCallbackInfo->FeCallbackHandle = Handle;\r
846 \r
847   //\r
848   // Post our VFR to the HII database.\r
849   //\r
850   PackageList = PreparePackages (1, &gBdsStringPackGuid, BmBin);\r
851   Status      = Hii->NewPack (Hii, PackageList, &HiiHandle);\r
852   gBS->FreePool (PackageList);\r
853 \r
854   BmmCallbackInfo->BmmHiiHandle = HiiHandle;\r
855 \r
856   PackageList                   = PreparePackages (1, &gBdsStringPackGuid, FEBin);\r
857   Status                        = Hii->NewPack (Hii, PackageList, &HiiHandle);\r
858   gBS->FreePool (PackageList);\r
859 \r
860   BmmCallbackInfo->FeHiiHandle = HiiHandle;\r
861 \r
862   //\r
863   // Allocate space for creation of Buffer\r
864   //\r
865   UpdateData = AllocateZeroPool (UPDATE_DATA_SIZE);\r
866   if (!UpdateData) {\r
867     SafeFreePool (BmmCallbackInfo->LoadContext);\r
868     SafeFreePool (BmmCallbackInfo);\r
869     return EFI_OUT_OF_RESOURCES;\r
870   }\r
871   //\r
872   // Initialize UpdateData structure\r
873   //\r
874   RefreshUpdateData (TRUE, (EFI_PHYSICAL_ADDRESS) (UINTN) BmmCallbackInfo->BmmCallbackHandle, FALSE, 0, 0);\r
875 \r
876   Location = (UINT8 *) &UpdateData->Data;\r
877 \r
878   InitializeStringDepository ();\r
879 \r
880   InitAllMenu (BmmCallbackInfo);\r
881 \r
882   CreateMenuStringToken (BmmCallbackInfo, BmmCallbackInfo->BmmHiiHandle, &ConsoleInpMenu);\r
883   CreateMenuStringToken (BmmCallbackInfo, BmmCallbackInfo->BmmHiiHandle, &ConsoleOutMenu);\r
884   CreateMenuStringToken (BmmCallbackInfo, BmmCallbackInfo->BmmHiiHandle, &ConsoleErrMenu);\r
885   CreateMenuStringToken (BmmCallbackInfo, BmmCallbackInfo->BmmHiiHandle, &BootOptionMenu);\r
886   CreateMenuStringToken (BmmCallbackInfo, BmmCallbackInfo->BmmHiiHandle, &DriverOptionMenu);\r
887   CreateMenuStringToken (BmmCallbackInfo, BmmCallbackInfo->BmmHiiHandle, &TerminalMenu);\r
888   CreateMenuStringToken (BmmCallbackInfo, BmmCallbackInfo->BmmHiiHandle, &DriverMenu);\r
889 \r
890   UpdateBootDelPage (BmmCallbackInfo);\r
891   UpdateDrvDelPage (BmmCallbackInfo);\r
892 \r
893   if (TerminalMenu.MenuNumber > 0) {\r
894     BmmCallbackInfo->CurrentTerminal = 0;\r
895     UpdateTerminalPage (BmmCallbackInfo);\r
896   }\r
897 \r
898   Location  = (UINT8 *) &UpdateData->Data;\r
899   Status    = EfiLibLocateProtocol (&gEfiLegacyBiosProtocolGuid, (VOID**) &LegacyBios);\r
900   if (!EFI_ERROR (Status)) {\r
901     //\r
902     // If LegacyBios Protocol is installed, add 3 tags about legacy boot option\r
903     // in BootOption form: legacy FD/HD/CD/NET/BEV\r
904     //\r
905     UpdateData->DataCount = 5;\r
906     CreateGotoOpCode (\r
907       FORM_SET_FD_ORDER_ID,\r
908       STRING_TOKEN (STR_FORM_SET_FD_ORDER_TITLE),\r
909       STRING_TOKEN (STR_FORM_SET_FD_ORDER_TITLE),\r
910       EFI_IFR_FLAG_INTERACTIVE | EFI_IFR_FLAG_NV_ACCESS,\r
911       FORM_SET_FD_ORDER_ID,\r
912       Location\r
913       );\r
914 \r
915     Location = Location + ((EFI_IFR_OP_HEADER *) Location)->Length;\r
916 \r
917     CreateGotoOpCode (\r
918       FORM_SET_HD_ORDER_ID,\r
919       STRING_TOKEN (STR_FORM_SET_HD_ORDER_TITLE),\r
920       STRING_TOKEN (STR_FORM_SET_HD_ORDER_TITLE),\r
921       EFI_IFR_FLAG_INTERACTIVE | EFI_IFR_FLAG_NV_ACCESS,\r
922       FORM_SET_HD_ORDER_ID,\r
923       Location\r
924       );\r
925 \r
926     Location = Location + ((EFI_IFR_OP_HEADER *) Location)->Length;\r
927 \r
928     CreateGotoOpCode (\r
929       FORM_SET_CD_ORDER_ID,\r
930       STRING_TOKEN (STR_FORM_SET_CD_ORDER_TITLE),\r
931       STRING_TOKEN (STR_FORM_SET_CD_ORDER_TITLE),\r
932       EFI_IFR_FLAG_INTERACTIVE | EFI_IFR_FLAG_NV_ACCESS,\r
933       FORM_SET_CD_ORDER_ID,\r
934       Location\r
935       );\r
936 \r
937     Location = Location + ((EFI_IFR_OP_HEADER *) Location)->Length;\r
938 \r
939     CreateGotoOpCode (\r
940       FORM_SET_NET_ORDER_ID,\r
941       STRING_TOKEN (STR_FORM_SET_NET_ORDER_TITLE),\r
942       STRING_TOKEN (STR_FORM_SET_NET_ORDER_TITLE),\r
943       EFI_IFR_FLAG_INTERACTIVE | EFI_IFR_FLAG_NV_ACCESS,\r
944       FORM_SET_NET_ORDER_ID,\r
945       Location\r
946       );\r
947 \r
948     Location = Location + ((EFI_IFR_OP_HEADER *) Location)->Length;\r
949 \r
950     CreateGotoOpCode (\r
951       FORM_SET_BEV_ORDER_ID,\r
952       STRING_TOKEN (STR_FORM_SET_BEV_ORDER_TITLE),\r
953       STRING_TOKEN (STR_FORM_SET_BEV_ORDER_TITLE),\r
954       EFI_IFR_FLAG_INTERACTIVE | EFI_IFR_FLAG_NV_ACCESS,\r
955       FORM_SET_BEV_ORDER_ID,\r
956       Location\r
957       );\r
958 \r
959     Hii->UpdateForm (\r
960           Hii,\r
961           BmmCallbackInfo->BmmHiiHandle,\r
962           (EFI_FORM_LABEL) FORM_BOOT_LEGACY_DEVICE_ID,\r
963           TRUE,\r
964           UpdateData\r
965           );\r
966   }\r
967   //\r
968   // Dispatch BMM main formset and File Explorer formset.\r
969   //\r
970   FormSetDispatcher (BmmCallbackInfo);\r
971 \r
972   Hii->ResetStrings (Hii, HiiHandle);\r
973 \r
974   CleanUpStringDepository ();\r
975 \r
976   if (EFI_ERROR (Status)) {\r
977     return Status;\r
978   }\r
979 \r
980   FreeAllMenu ();\r
981 \r
982   SafeFreePool (BmmCallbackInfo->LoadContext);\r
983   BmmCallbackInfo->LoadContext = NULL;\r
984   SafeFreePool (BmmCallbackInfo);\r
985   BmmCallbackInfo = NULL;\r
986   SafeFreePool (UpdateData);\r
987   UpdateData = NULL;\r
988 \r
989   return Status;\r
990 }\r
991 \r
992 VOID\r
993 InitAllMenu (\r
994   IN  BMM_CALLBACK_DATA    *CallbackData\r
995   )\r
996 {\r
997   InitializeListHead (&BootOptionMenu.Head);\r
998   InitializeListHead (&DriverOptionMenu.Head);\r
999   BOpt_GetBootOptions (CallbackData);\r
1000   BOpt_GetDriverOptions (CallbackData);\r
1001   BOpt_GetLegacyOptions ();\r
1002   InitializeListHead (&FsOptionMenu.Head);\r
1003   BOpt_FindDrivers ();\r
1004   InitializeListHead (&DirectoryMenu.Head);\r
1005   InitializeListHead (&ConsoleInpMenu.Head);\r
1006   InitializeListHead (&ConsoleOutMenu.Head);\r
1007   InitializeListHead (&ConsoleErrMenu.Head);\r
1008   InitializeListHead (&TerminalMenu.Head);\r
1009   LocateSerialIo ();\r
1010   GetAllConsoles ();\r
1011 }\r
1012 \r
1013 VOID\r
1014 FreeAllMenu (\r
1015   VOID\r
1016   )\r
1017 {\r
1018   BOpt_FreeMenu (&DirectoryMenu);\r
1019   BOpt_FreeMenu (&FsOptionMenu);\r
1020   BOpt_FreeMenu (&BootOptionMenu);\r
1021   BOpt_FreeMenu (&DriverOptionMenu);\r
1022   BOpt_FreeMenu (&DriverMenu);\r
1023   BOpt_FreeLegacyOptions ();\r
1024   FreeAllConsoles ();\r
1025 }\r
1026 \r
1027 VOID\r
1028 InitializeStringDepository (\r
1029   VOID\r
1030   )\r
1031 /*++\r
1032 Routine Description:\r
1033   Intialize all the string depositories.\r
1034 \r
1035 Arguments:\r
1036   None.\r
1037 \r
1038 Returns:\r
1039   None.  \r
1040 --*/\r
1041 {\r
1042   STRING_DEPOSITORY *StringDepository;\r
1043   StringDepository              = AllocateZeroPool (sizeof (STRING_DEPOSITORY) * STRING_DEPOSITORY_NUMBER);\r
1044   FileOptionStrDepository       = StringDepository++;\r
1045   ConsoleOptionStrDepository    = StringDepository++;\r
1046   BootOptionStrDepository       = StringDepository++;\r
1047   BootOptionHelpStrDepository   = StringDepository++;\r
1048   DriverOptionStrDepository     = StringDepository++;\r
1049   DriverOptionHelpStrDepository = StringDepository++;\r
1050   TerminalStrDepository         = StringDepository;\r
1051 }\r
1052 \r
1053 STRING_REF\r
1054 GetStringTokenFromDepository (\r
1055   IN   BMM_CALLBACK_DATA     *CallbackData,\r
1056   IN   STRING_DEPOSITORY     *StringDepository\r
1057   )\r
1058 /*++\r
1059 Routine Description:\r
1060   Fetch a usable string node from the string depository and return the string token.\r
1061 \r
1062 Arguments:\r
1063   StringDepository       - Pointer of the string depository.\r
1064 \r
1065 Returns:\r
1066   STRING_REF             - String token.\r
1067 --*/\r
1068 {\r
1069   STRING_LIST_NODE  *CurrentListNode;\r
1070   STRING_LIST_NODE  *NextListNode;\r
1071 \r
1072   CurrentListNode = StringDepository->CurrentNode;\r
1073 \r
1074   if ((NULL != CurrentListNode) && (NULL != CurrentListNode->Next)) {\r
1075     //\r
1076     // Fetch one reclaimed node from the list.\r
1077     //\r
1078     NextListNode = StringDepository->CurrentNode->Next;\r
1079   } else {\r
1080     //\r
1081     // If there is no usable node in the list, update the list.\r
1082     //\r
1083     NextListNode = AllocateZeroPool (sizeof (STRING_LIST_NODE));\r
1084 \r
1085     CallbackData->Hii->NewString (\r
1086                         CallbackData->Hii,\r
1087                         NULL,\r
1088                         CallbackData->BmmHiiHandle,\r
1089                         &(NextListNode->StringToken),\r
1090                         L" "\r
1091                         );\r
1092 \r
1093     ASSERT (NextListNode->StringToken != 0);\r
1094 \r
1095     StringDepository->TotalNodeNumber++;\r
1096 \r
1097     if (NULL == CurrentListNode) {\r
1098       StringDepository->ListHead = NextListNode;\r
1099     } else {\r
1100       CurrentListNode->Next = NextListNode;\r
1101     }\r
1102   }\r
1103 \r
1104   StringDepository->CurrentNode = NextListNode;\r
1105 \r
1106   return StringDepository->CurrentNode->StringToken;\r
1107 }\r
1108 \r
1109 VOID\r
1110 ReclaimStringDepository (\r
1111   VOID\r
1112   )\r
1113 /*++\r
1114 Routine Description:\r
1115   Reclaim string depositories by moving the current node pointer to list head..\r
1116 \r
1117 Arguments:\r
1118   None.\r
1119 \r
1120 Returns:\r
1121   None.\r
1122 --*/\r
1123 {\r
1124   UINTN             DepositoryIndex;\r
1125   STRING_DEPOSITORY *StringDepository;\r
1126 \r
1127   StringDepository = FileOptionStrDepository;\r
1128   for (DepositoryIndex = 0; DepositoryIndex < STRING_DEPOSITORY_NUMBER; DepositoryIndex++) {\r
1129     StringDepository->CurrentNode = StringDepository->ListHead;\r
1130     StringDepository++;\r
1131   }\r
1132 }\r
1133 \r
1134 VOID\r
1135 CleanUpStringDepository (\r
1136   VOID\r
1137   )\r
1138 /*++\r
1139 Routine Description:\r
1140   Release resource for all the string depositories.\r
1141 \r
1142 Arguments:\r
1143   None.\r
1144 \r
1145 Returns:\r
1146   None.\r
1147 --*/\r
1148 {\r
1149   UINTN             NodeIndex;\r
1150   UINTN             DepositoryIndex;\r
1151   STRING_LIST_NODE  *CurrentListNode;\r
1152   STRING_LIST_NODE  *NextListNode;\r
1153   STRING_DEPOSITORY *StringDepository;\r
1154 \r
1155   //\r
1156   // Release string list nodes.\r
1157   //\r
1158   StringDepository = FileOptionStrDepository;\r
1159   for (DepositoryIndex = 0; DepositoryIndex < STRING_DEPOSITORY_NUMBER; DepositoryIndex++) {\r
1160     CurrentListNode = StringDepository->ListHead;\r
1161     for (NodeIndex = 0; NodeIndex < StringDepository->TotalNodeNumber; NodeIndex++) {\r
1162       NextListNode = CurrentListNode->Next;\r
1163       SafeFreePool (CurrentListNode);\r
1164       CurrentListNode = NextListNode;\r
1165     }\r
1166 \r
1167     StringDepository++;\r
1168   }\r
1169   //\r
1170   // Release string depository.\r
1171   //\r
1172   SafeFreePool (FileOptionStrDepository);\r
1173 }\r
1174 \r
1175 EFI_STATUS\r
1176 BdsStartBootMaint (\r
1177   VOID\r
1178   )\r
1179 /*++\r
1180 \r
1181 Routine Description:\r
1182   Start boot maintenance manager\r
1183 \r
1184 Arguments:\r
1185 \r
1186 Returns:\r
1187 \r
1188 --*/\r
1189 {\r
1190   EFI_STATUS  Status;\r
1191   LIST_ENTRY  BdsBootOptionList;\r
1192 \r
1193   InitializeListHead (&BdsBootOptionList);\r
1194 \r
1195   //\r
1196   // Connect all prior to entering the platform setup menu.\r
1197   //\r
1198   if (!gConnectAllHappened) {\r
1199     BdsLibConnectAllDriversToAllControllers ();\r
1200     gConnectAllHappened = TRUE;\r
1201   }\r
1202   //\r
1203   // Have chance to enumerate boot device\r
1204   //\r
1205   BdsLibEnumerateAllBootOption (&BdsBootOptionList);\r
1206 \r
1207   //\r
1208   // Init the BMM\r
1209   //\r
1210   Status = InitializeBM ();\r
1211 \r
1212   return Status;\r
1213 }\r
1214 \r
1215 EFI_STATUS\r
1216 FormSetDispatcher (\r
1217   IN  BMM_CALLBACK_DATA    *CallbackData\r
1218   )\r
1219 /*++\r
1220 \r
1221 Routine Description:\r
1222   Dispatch BMM formset and FileExplorer formset.\r
1223 \r
1224 Arguments:\r
1225 \r
1226 Returns:\r
1227 \r
1228 --*/\r
1229 {\r
1230   EFI_FORM_BROWSER_PROTOCOL *FormConfig;\r
1231   UINT8                     *Location;\r
1232   EFI_STATUS                Status;\r
1233   UINTN                     Index;\r
1234   BM_MENU_ENTRY             *NewMenuEntry;\r
1235   BM_FILE_CONTEXT           *NewFileContext;\r
1236   BOOLEAN                        BootMaintMenuResetRequired;\r
1237 \r
1238   Location        = NULL;\r
1239   Index           = 0;\r
1240   NewMenuEntry    = NULL;\r
1241   NewFileContext  = NULL;\r
1242 \r
1243   //\r
1244   // There should only be one Form Configuration protocol\r
1245   //\r
1246   Status = EfiLibLocateProtocol (&gEfiFormBrowserProtocolGuid, (VOID**) &FormConfig);\r
1247   if (EFI_ERROR (Status)) {\r
1248     return Status;\r
1249   }\r
1250 \r
1251   while (1) {\r
1252     UpdatePageId (CallbackData, FORM_MAIN_ID);\r
1253 \r
1254     BootMaintMenuResetRequired = FALSE;\r
1255     Status = FormConfig->SendForm (\r
1256                           FormConfig,\r
1257                           TRUE,\r
1258                           &(CallbackData->BmmHiiHandle),\r
1259                           1,\r
1260                           NULL,\r
1261                           NULL,\r
1262                           (UINT8 *) CallbackData->BmmFakeNvData,\r
1263                           NULL,\r
1264                           &BootMaintMenuResetRequired\r
1265                           );\r
1266 \r
1267     if (BootMaintMenuResetRequired) {\r
1268       EnableResetRequired ();\r
1269     }\r
1270 \r
1271     ReclaimStringDepository ();\r
1272 \r
1273     //\r
1274     // When this Formset returns, check if we are going to explore files.\r
1275     //\r
1276     if (INACTIVE_STATE != CallbackData->FeCurrentState) {\r
1277       UpdateFileExplorer (CallbackData, 0);\r
1278 \r
1279       BootMaintMenuResetRequired = FALSE;\r
1280       Status = FormConfig->SendForm (\r
1281                             FormConfig,\r
1282                             TRUE,\r
1283                             &(CallbackData->FeHiiHandle),\r
1284                             1,\r
1285                             NULL,\r
1286                             NULL,\r
1287                             NULL,\r
1288                             NULL,\r
1289                             &BootMaintMenuResetRequired\r
1290                             );\r
1291 \r
1292       if (BootMaintMenuResetRequired) {\r
1293         EnableResetRequired ();\r
1294       }\r
1295 \r
1296       CallbackData->FeCurrentState    = INACTIVE_STATE;\r
1297       CallbackData->FeDisplayContext  = UNKNOWN_CONTEXT;\r
1298       ReclaimStringDepository ();\r
1299     } else {\r
1300       break;\r
1301     }\r
1302   }\r
1303 \r
1304   return Status;\r
1305 }\r
1306 \r
1307 VOID\r
1308 CreateCallbackPacket (\r
1309   OUT EFI_HII_CALLBACK_PACKET         **Packet,\r
1310   IN  UINT16                          Flags\r
1311   )\r
1312 {\r
1313   *Packet = (EFI_HII_CALLBACK_PACKET *) AllocateZeroPool (sizeof (EFI_HII_CALLBACK_PACKET) + 2);\r
1314   ASSERT (*Packet != NULL);\r
1315 \r
1316   (*Packet)->DataArray.EntryCount   = 1;\r
1317   (*Packet)->DataArray.NvRamMap     = NULL;\r
1318   ((EFI_IFR_DATA_ENTRY *) (&((*Packet)->DataArray) + 1))->Flags  = Flags;\r
1319 }\r