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