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