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