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