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