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