]> git.proxmox.com Git - mirror_edk2.git/blob - EdkUnixPkg/Dxe/PlatformBds/Generic/BootMaint/BootMaint.c
Unix version of EFI emulator
[mirror_edk2.git] / EdkUnixPkg / 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 Private->HandleContext = (BM_HANDLE_CONTEXT *) NewMenuEntry->VariableContext;
453
454 CleanUpPage (FORM_DRV_ADD_HANDLE_DESC_ID, Private);
455
456 Private->MenuEntry = NewMenuEntry;
457 Private->LoadContext->FilePathList = Private->HandleContext->DevicePath;
458
459 UpdateDriverAddHandleDescPage (Private);
460 }
461 }
462
463 return EFI_SUCCESS;
464 }
465
466 EFI_STATUS
467 ApplyChangeHandler (
468 IN BMM_CALLBACK_DATA *Private,
469 IN BMM_FAKE_NV_DATA *CurrentFakeNVMap,
470 IN FORM_ID FormId
471 )
472 /*++
473
474 Routine Description:
475
476 Function handling request to apply changes for BMM pages.
477
478 Arguments:
479
480 Private - Pointer to callback data buffer.
481 CurrentFakeNVMap - Pointer to buffer holding data of various values used by BMM
482 FormId - ID of the form which has sent the request to apply change.
483
484 Returns:
485
486 EFI_SUCCESS - Change successfully applied.
487 Other - Error occurs while trying to apply changes.
488
489 --*/
490 {
491 BM_CONSOLE_CONTEXT *NewConsoleContext;
492 BM_TERMINAL_CONTEXT *NewTerminalContext;
493 BM_LOAD_CONTEXT *NewLoadContext;
494 BM_MENU_ENTRY *NewMenuEntry;
495 EFI_STATUS Status;
496 UINT16 Index;
497
498 Status = EFI_SUCCESS;
499
500 switch (FormId) {
501 case FORM_SET_FD_ORDER_ID:
502 case FORM_SET_HD_ORDER_ID:
503 case FORM_SET_CD_ORDER_ID:
504 case FORM_SET_NET_ORDER_ID:
505 case FORM_SET_BEV_ORDER_ID:
506 Var_UpdateBBSOption (Private);
507 break;
508
509 case FORM_BOOT_DEL_ID:
510 for (Index = 0; Index < BootOptionMenu.MenuNumber; Index++) {
511 NewMenuEntry = BOpt_GetMenuEntry (&BootOptionMenu, Index);
512 NewLoadContext = (BM_LOAD_CONTEXT *) NewMenuEntry->VariableContext;
513 NewLoadContext->Deleted = CurrentFakeNVMap->BootOptionDel[Index];
514 }
515
516 Var_DelBootOption ();
517 break;
518
519 case FORM_DRV_DEL_ID:
520 for (Index = 0; Index < DriverOptionMenu.MenuNumber; Index++) {
521 NewMenuEntry = BOpt_GetMenuEntry (&DriverOptionMenu, Index);
522 NewLoadContext = (BM_LOAD_CONTEXT *) NewMenuEntry->VariableContext;
523 NewLoadContext->Deleted = CurrentFakeNVMap->DriverOptionDel[Index];
524 }
525
526 Var_DelDriverOption ();
527 break;
528
529 case FORM_BOOT_CHG_ID:
530 Status = Var_UpdateBootOrder (Private);
531 break;
532
533 case FORM_DRV_CHG_ID:
534 Status = Var_UpdateDriverOrder (Private);
535 break;
536
537 case FORM_TIME_OUT_ID:
538 Status = gRT->SetVariable (
539 L"Timeout",
540 &gEfiGlobalVariableGuid,
541 VAR_FLAG,
542 sizeof (UINT16),
543 &(CurrentFakeNVMap->BootTimeOut)
544 );
545 if (EFI_ERROR (Status)) {
546 goto Error;
547 }
548
549 Private->BmmOldFakeNVData.BootTimeOut = CurrentFakeNVMap->BootTimeOut;
550 break;
551
552 case FORM_BOOT_NEXT_ID:
553 Status = Var_UpdateBootNext (Private);
554 break;
555
556 case FORM_CON_COM_ID:
557 NewMenuEntry = BOpt_GetMenuEntry (&TerminalMenu, Private->CurrentTerminal);
558
559 NewTerminalContext = (BM_TERMINAL_CONTEXT *) NewMenuEntry->VariableContext;
560
561 NewTerminalContext->BaudRateIndex = CurrentFakeNVMap->COMBaudRate;
562 NewTerminalContext->BaudRate = BaudRateList[CurrentFakeNVMap->COMBaudRate].Value;
563 NewTerminalContext->DataBitsIndex = CurrentFakeNVMap->COMDataRate;
564 NewTerminalContext->DataBits = (UINT8) DataBitsList[CurrentFakeNVMap->COMDataRate].Value;
565 NewTerminalContext->StopBitsIndex = CurrentFakeNVMap->COMStopBits;
566 NewTerminalContext->StopBits = (UINT8) StopBitsList[CurrentFakeNVMap->COMStopBits].Value;
567 NewTerminalContext->ParityIndex = CurrentFakeNVMap->COMParity;
568 NewTerminalContext->Parity = (UINT8) ParityList[CurrentFakeNVMap->COMParity].Value;
569 NewTerminalContext->TerminalType = CurrentFakeNVMap->COMTerminalType;
570
571 ChangeTerminalDevicePath (
572 NewTerminalContext->DevicePath,
573 FALSE
574 );
575
576 Var_UpdateConsoleInpOption ();
577 Var_UpdateConsoleOutOption ();
578 Var_UpdateErrorOutOption ();
579 break;
580
581 case FORM_CON_IN_ID:
582 for (Index = 0; Index < ConsoleInpMenu.MenuNumber; Index++) {
583 NewMenuEntry = BOpt_GetMenuEntry (&ConsoleInpMenu, Index);
584 NewConsoleContext = (BM_CONSOLE_CONTEXT *) NewMenuEntry->VariableContext;
585 NewConsoleContext->IsActive = CurrentFakeNVMap->ConsoleCheck[Index];
586 }
587
588 for (Index = 0; Index < TerminalMenu.MenuNumber; Index++) {
589 NewMenuEntry = BOpt_GetMenuEntry (&TerminalMenu, Index);
590 NewTerminalContext = (BM_TERMINAL_CONTEXT *) NewMenuEntry->VariableContext;
591 NewTerminalContext->IsConIn = CurrentFakeNVMap->ConsoleCheck[Index + ConsoleInpMenu.MenuNumber];
592 }
593
594 Var_UpdateConsoleInpOption ();
595 break;
596
597 case FORM_CON_OUT_ID:
598 for (Index = 0; Index < ConsoleOutMenu.MenuNumber; Index++) {
599 NewMenuEntry = BOpt_GetMenuEntry (&ConsoleOutMenu, Index);
600 NewConsoleContext = (BM_CONSOLE_CONTEXT *) NewMenuEntry->VariableContext;
601 NewConsoleContext->IsActive = CurrentFakeNVMap->ConsoleCheck[Index];
602 }
603
604 for (Index = 0; Index < TerminalMenu.MenuNumber; Index++) {
605 NewMenuEntry = BOpt_GetMenuEntry (&TerminalMenu, Index);
606 NewTerminalContext = (BM_TERMINAL_CONTEXT *) NewMenuEntry->VariableContext;
607 NewTerminalContext->IsConOut = CurrentFakeNVMap->ConsoleCheck[Index + ConsoleOutMenu.MenuNumber];
608 }
609
610 Var_UpdateConsoleOutOption ();
611 break;
612
613 case FORM_CON_ERR_ID:
614 for (Index = 0; Index < ConsoleErrMenu.MenuNumber; Index++) {
615 NewMenuEntry = BOpt_GetMenuEntry (&ConsoleErrMenu, Index);
616 NewConsoleContext = (BM_CONSOLE_CONTEXT *) NewMenuEntry->VariableContext;
617 NewConsoleContext->IsActive = CurrentFakeNVMap->ConsoleCheck[Index];
618 }
619
620 for (Index = 0; Index < TerminalMenu.MenuNumber; Index++) {
621 NewMenuEntry = BOpt_GetMenuEntry (&TerminalMenu, Index);
622 NewTerminalContext = (BM_TERMINAL_CONTEXT *) NewMenuEntry->VariableContext;
623 NewTerminalContext->IsStdErr = CurrentFakeNVMap->ConsoleCheck[Index + ConsoleErrMenu.MenuNumber];
624 }
625
626 Var_UpdateErrorOutOption ();
627 break;
628
629 case FORM_DRV_ADD_HANDLE_DESC_ID:
630 Status = Var_UpdateDriverOption (
631 Private,
632 Private->BmmHiiHandle,
633 CurrentFakeNVMap->DriverAddHandleDesc,
634 CurrentFakeNVMap->DriverAddHandleOptionalData,
635 CurrentFakeNVMap->DriverAddForceReconnect
636 );
637 if (EFI_ERROR (Status)) {
638 goto Error;
639 }
640
641 BOpt_GetDriverOptions (Private);
642 CreateMenuStringToken (Private, Private->BmmHiiHandle, &DriverOptionMenu);
643 break;
644
645 default:
646 break;
647 }
648
649 Error:
650 return Status;
651 }
652
653 VOID
654 DiscardChangeHandler (
655 IN BMM_CALLBACK_DATA *Private,
656 IN BMM_FAKE_NV_DATA *CurrentFakeNVMap
657 )
658 {
659 UINT16 Index;
660
661 switch (Private->BmmPreviousPageId) {
662 case FORM_BOOT_CHG_ID:
663 case FORM_DRV_CHG_ID:
664 CopyMem (CurrentFakeNVMap->OptionOrder, Private->BmmOldFakeNVData.OptionOrder, 100);
665 break;
666
667 case FORM_BOOT_DEL_ID:
668 for (Index = 0; Index < BootOptionMenu.MenuNumber; Index++) {
669 CurrentFakeNVMap->BootOptionDel[Index] = 0x00;
670 }
671 break;
672
673 case FORM_DRV_DEL_ID:
674 for (Index = 0; Index < DriverOptionMenu.MenuNumber; Index++) {
675 CurrentFakeNVMap->DriverOptionDel[Index] = 0x00;
676 }
677 break;
678
679 case FORM_BOOT_NEXT_ID:
680 CurrentFakeNVMap->BootNext = Private->BmmOldFakeNVData.BootNext;
681 break;
682
683 case FORM_TIME_OUT_ID:
684 CurrentFakeNVMap->BootTimeOut = Private->BmmOldFakeNVData.BootTimeOut;
685 break;
686
687 case FORM_DRV_ADD_HANDLE_DESC_ID:
688 case FORM_DRV_ADD_FILE_ID:
689 case FORM_DRV_ADD_HANDLE_ID:
690 CurrentFakeNVMap->DriverAddHandleDesc[0] = 0x0000;
691 CurrentFakeNVMap->DriverAddHandleOptionalData[0] = 0x0000;
692 break;
693
694 default:
695 break;
696 }
697 }
698
699 EFI_STATUS
700 EFIAPI
701 NvWrite (
702 IN EFI_FORM_CALLBACK_PROTOCOL *This,
703 IN CHAR16 *VariableName,
704 IN EFI_GUID *VendorGuid,
705 OUT UINT32 Attributes OPTIONAL,
706 IN OUT UINTN DataSize,
707 OUT VOID *Buffer,
708 OUT BOOLEAN *ResetRequired
709 )
710 {
711 //
712 // Do nothing here. Just to catch the F10, we use "Apply Changes" tag to save.
713 //
714 return EFI_SUCCESS;
715 }
716
717 EFI_STATUS
718 InitializeBM (
719 VOID
720 )
721 /*++
722 Routine Description:
723
724 Initialize the Boot Maintenance Utitliy
725
726 Arguments:
727
728 ImageHandle - caller provided handle
729
730 SystemTable - caller provided system tables
731
732 Returns:
733
734 EFI_SUCCESS - utility ended successfully
735
736 others - contain some errors
737
738 --*/
739 {
740 EFI_LEGACY_BIOS_PROTOCOL *LegacyBios;
741 EFI_HII_PACKAGES *PackageList;
742 BMM_CALLBACK_DATA *BmmCallbackInfo;
743 EFI_HII_PROTOCOL *Hii;
744 EFI_HII_HANDLE HiiHandle;
745 EFI_STATUS Status;
746 EFI_HANDLE Handle;
747 UINT8 *Ptr;
748 UINT8 *Location;
749
750 Status = EFI_SUCCESS;
751 UpdateData = NULL;
752 //
753 // Initialize EfiUtilityLib and EfiDriverLib
754 // Since many functions in UtilityLib must be used and
755 // SetupBrowser use DriverLib
756 //
757 //
758 // There should be only one EFI_HII_PROTOCOL Image
759 //
760 Status = EfiLibLocateProtocol (&gEfiHiiProtocolGuid, &Hii);
761 if (EFI_ERROR (Status)) {
762 return Status;
763 }
764 //
765 // Create CallbackData structures for Driver Callback
766 //
767 BmmCallbackInfo = AllocateZeroPool (sizeof (BMM_CALLBACK_DATA));
768 if (!BmmCallbackInfo) {
769 return EFI_OUT_OF_RESOURCES;
770 }
771 //
772 // Create LoadOption in BmmCallbackInfo for Driver Callback
773 //
774 Ptr = AllocateZeroPool (sizeof (BM_LOAD_CONTEXT) + sizeof (BM_FILE_CONTEXT) + sizeof (BM_HANDLE_CONTEXT) + sizeof (BM_MENU_ENTRY));
775 if (!Ptr) {
776 SafeFreePool (BmmCallbackInfo);
777 return EFI_OUT_OF_RESOURCES;
778 }
779 //
780 // Initialize Bmm callback data.
781 //
782 BmmCallbackInfo->LoadContext = (BM_LOAD_CONTEXT *) Ptr;
783 Ptr += sizeof (BM_LOAD_CONTEXT);
784
785 BmmCallbackInfo->FileContext = (BM_FILE_CONTEXT *) Ptr;
786 Ptr += sizeof (BM_FILE_CONTEXT);
787
788 BmmCallbackInfo->HandleContext = (BM_HANDLE_CONTEXT *) Ptr;
789 Ptr += sizeof (BM_HANDLE_CONTEXT);
790
791 BmmCallbackInfo->MenuEntry = (BM_MENU_ENTRY *) Ptr;
792
793 BmmCallbackInfo->BmmFakeNvData = &BmmCallbackInfo->BmmOldFakeNVData;
794
795 ZeroMem (BmmCallbackInfo->BmmFakeNvData, sizeof (BMM_FAKE_NV_DATA));
796
797 BmmCallbackInfo->Signature = BMM_CALLBACK_DATA_SIGNATURE;
798 BmmCallbackInfo->Hii = Hii;
799 BmmCallbackInfo->BmmDriverCallback.NvRead = NULL;
800 BmmCallbackInfo->BmmDriverCallback.NvWrite = NvWrite;
801 BmmCallbackInfo->BmmDriverCallback.Callback = DriverCallback;
802 BmmCallbackInfo->BmmPreviousPageId = FORM_MAIN_ID;
803 BmmCallbackInfo->BmmCurrentPageId = FORM_MAIN_ID;
804 BmmCallbackInfo->FeDriverCallback.NvRead = NULL;
805 BmmCallbackInfo->FeDriverCallback.NvWrite = NvWrite;
806 BmmCallbackInfo->FeDriverCallback.Callback = FileExplorerCallback;
807 BmmCallbackInfo->FeCurrentState = INACTIVE_STATE;
808 BmmCallbackInfo->FeDisplayContext = UNKNOWN_CONTEXT;
809
810 //
811 // Install bmm callback protocol interface
812 //
813 Handle = NULL;
814 Status = gBS->InstallProtocolInterface (
815 &Handle,
816 &gEfiFormCallbackProtocolGuid,
817 EFI_NATIVE_INTERFACE,
818 &BmmCallbackInfo->BmmDriverCallback
819 );
820
821 if (EFI_ERROR (Status)) {
822 return Status;
823 }
824
825 BmmCallbackInfo->BmmCallbackHandle = Handle;
826
827 //
828 // Install file explorer callback protocol interface
829 //
830 Handle = NULL;
831 Status = gBS->InstallProtocolInterface (
832 &Handle,
833 &gEfiFormCallbackProtocolGuid,
834 EFI_NATIVE_INTERFACE,
835 &BmmCallbackInfo->FeDriverCallback
836 );
837
838 if (EFI_ERROR (Status)) {
839 return Status;
840 }
841
842 BmmCallbackInfo->FeCallbackHandle = Handle;
843
844 //
845 // Post our VFR to the HII database.
846 //
847 PackageList = PreparePackages (1, &gBdsStringPackGuid, BmBin);
848 Status = Hii->NewPack (Hii, PackageList, &HiiHandle);
849 gBS->FreePool (PackageList);
850
851 BmmCallbackInfo->BmmHiiHandle = HiiHandle;
852
853 PackageList = PreparePackages (1, &gBdsStringPackGuid, FEBin);
854 Status = Hii->NewPack (Hii, PackageList, &HiiHandle);
855 gBS->FreePool (PackageList);
856
857 BmmCallbackInfo->FeHiiHandle = HiiHandle;
858
859 //
860 // Allocate space for creation of Buffer
861 //
862 UpdateData = AllocateZeroPool (UPDATE_DATA_SIZE);
863 if (!UpdateData) {
864 SafeFreePool (BmmCallbackInfo->LoadContext);
865 SafeFreePool (BmmCallbackInfo);
866 return EFI_OUT_OF_RESOURCES;
867 }
868 //
869 // Initialize UpdateData structure
870 //
871 RefreshUpdateData (TRUE, (EFI_PHYSICAL_ADDRESS) (UINTN) BmmCallbackInfo->BmmCallbackHandle, FALSE, 0, 0);
872
873 Location = (UINT8 *) &UpdateData->Data;
874
875 InitializeStringDepository ();
876
877 InitAllMenu (BmmCallbackInfo);
878
879 CreateMenuStringToken (BmmCallbackInfo, BmmCallbackInfo->BmmHiiHandle, &ConsoleInpMenu);
880 CreateMenuStringToken (BmmCallbackInfo, BmmCallbackInfo->BmmHiiHandle, &ConsoleOutMenu);
881 CreateMenuStringToken (BmmCallbackInfo, BmmCallbackInfo->BmmHiiHandle, &ConsoleErrMenu);
882 CreateMenuStringToken (BmmCallbackInfo, BmmCallbackInfo->BmmHiiHandle, &BootOptionMenu);
883 CreateMenuStringToken (BmmCallbackInfo, BmmCallbackInfo->BmmHiiHandle, &DriverOptionMenu);
884 CreateMenuStringToken (BmmCallbackInfo, BmmCallbackInfo->BmmHiiHandle, &TerminalMenu);
885 CreateMenuStringToken (BmmCallbackInfo, BmmCallbackInfo->BmmHiiHandle, &DriverMenu);
886
887 UpdateBootDelPage (BmmCallbackInfo);
888 UpdateDrvDelPage (BmmCallbackInfo);
889
890 if (TerminalMenu.MenuNumber > 0) {
891 BmmCallbackInfo->CurrentTerminal = 0;
892 UpdateTerminalPage (BmmCallbackInfo);
893 }
894
895 Location = (UINT8 *) &UpdateData->Data;
896 Status = EfiLibLocateProtocol (&gEfiLegacyBiosProtocolGuid, &LegacyBios);
897 if (!EFI_ERROR (Status)) {
898 //
899 // If LegacyBios Protocol is installed, add 3 tags about legacy boot option
900 // in BootOption form: legacy FD/HD/CD/NET/BEV
901 //
902 UpdateData->DataCount = 5;
903 CreateGotoOpCode (
904 FORM_SET_FD_ORDER_ID,
905 STRING_TOKEN (STR_FORM_SET_FD_ORDER_TITLE),
906 STRING_TOKEN (STR_FORM_SET_FD_ORDER_TITLE),
907 EFI_IFR_FLAG_INTERACTIVE | EFI_IFR_FLAG_NV_ACCESS,
908 FORM_SET_FD_ORDER_ID,
909 Location
910 );
911
912 Location = Location + ((EFI_IFR_OP_HEADER *) Location)->Length;
913
914 CreateGotoOpCode (
915 FORM_SET_HD_ORDER_ID,
916 STRING_TOKEN (STR_FORM_SET_HD_ORDER_TITLE),
917 STRING_TOKEN (STR_FORM_SET_HD_ORDER_TITLE),
918 EFI_IFR_FLAG_INTERACTIVE | EFI_IFR_FLAG_NV_ACCESS,
919 FORM_SET_HD_ORDER_ID,
920 Location
921 );
922
923 Location = Location + ((EFI_IFR_OP_HEADER *) Location)->Length;
924
925 CreateGotoOpCode (
926 FORM_SET_CD_ORDER_ID,
927 STRING_TOKEN (STR_FORM_SET_CD_ORDER_TITLE),
928 STRING_TOKEN (STR_FORM_SET_CD_ORDER_TITLE),
929 EFI_IFR_FLAG_INTERACTIVE | EFI_IFR_FLAG_NV_ACCESS,
930 FORM_SET_CD_ORDER_ID,
931 Location
932 );
933
934 Location = Location + ((EFI_IFR_OP_HEADER *) Location)->Length;
935
936 CreateGotoOpCode (
937 FORM_SET_NET_ORDER_ID,
938 STRING_TOKEN (STR_FORM_SET_NET_ORDER_TITLE),
939 STRING_TOKEN (STR_FORM_SET_NET_ORDER_TITLE),
940 EFI_IFR_FLAG_INTERACTIVE | EFI_IFR_FLAG_NV_ACCESS,
941 FORM_SET_NET_ORDER_ID,
942 Location
943 );
944
945 Location = Location + ((EFI_IFR_OP_HEADER *) Location)->Length;
946
947 CreateGotoOpCode (
948 FORM_SET_BEV_ORDER_ID,
949 STRING_TOKEN (STR_FORM_SET_BEV_ORDER_TITLE),
950 STRING_TOKEN (STR_FORM_SET_BEV_ORDER_TITLE),
951 EFI_IFR_FLAG_INTERACTIVE | EFI_IFR_FLAG_NV_ACCESS,
952 FORM_SET_BEV_ORDER_ID,
953 Location
954 );
955
956 Hii->UpdateForm (
957 Hii,
958 BmmCallbackInfo->BmmHiiHandle,
959 (EFI_FORM_LABEL) FORM_BOOT_LEGACY_DEVICE_ID,
960 TRUE,
961 UpdateData
962 );
963 }
964 //
965 // Dispatch BMM main formset and File Explorer formset.
966 //
967 FormSetDispatcher (BmmCallbackInfo);
968
969 Hii->ResetStrings (Hii, HiiHandle);
970
971 CleanUpStringDepository ();
972
973 if (EFI_ERROR (Status)) {
974 return Status;
975 }
976
977 FreeAllMenu ();
978
979 SafeFreePool (BmmCallbackInfo->LoadContext);
980 BmmCallbackInfo->LoadContext = NULL;
981 SafeFreePool (BmmCallbackInfo);
982 BmmCallbackInfo = NULL;
983 SafeFreePool (UpdateData);
984 UpdateData = NULL;
985
986 return Status;
987 }
988
989 VOID
990 InitAllMenu (
991 IN BMM_CALLBACK_DATA *CallbackData
992 )
993 {
994 InitializeListHead (&BootOptionMenu.Head);
995 InitializeListHead (&DriverOptionMenu.Head);
996 BOpt_GetBootOptions (CallbackData);
997 BOpt_GetDriverOptions (CallbackData);
998 BOpt_GetLegacyOptions ();
999 InitializeListHead (&FsOptionMenu.Head);
1000 BOpt_FindDrivers ();
1001 InitializeListHead (&DirectoryMenu.Head);
1002 InitializeListHead (&ConsoleInpMenu.Head);
1003 InitializeListHead (&ConsoleOutMenu.Head);
1004 InitializeListHead (&ConsoleErrMenu.Head);
1005 InitializeListHead (&TerminalMenu.Head);
1006 LocateSerialIo ();
1007 GetAllConsoles ();
1008 }
1009
1010 VOID
1011 FreeAllMenu (
1012 VOID
1013 )
1014 {
1015 BOpt_FreeMenu (&DirectoryMenu);
1016 BOpt_FreeMenu (&FsOptionMenu);
1017 BOpt_FreeMenu (&BootOptionMenu);
1018 BOpt_FreeMenu (&DriverOptionMenu);
1019 BOpt_FreeMenu (&DriverMenu);
1020 BOpt_FreeLegacyOptions ();
1021 FreeAllConsoles ();
1022 }
1023
1024 VOID
1025 InitializeStringDepository (
1026 VOID
1027 )
1028 /*++
1029 Routine Description:
1030 Intialize all the string depositories.
1031
1032 Arguments:
1033 None.
1034
1035 Returns:
1036 None.
1037 --*/
1038 {
1039 STRING_DEPOSITORY *StringDepository;
1040 StringDepository = AllocateZeroPool (sizeof (STRING_DEPOSITORY) * STRING_DEPOSITORY_NUMBER);
1041 FileOptionStrDepository = StringDepository++;
1042 ConsoleOptionStrDepository = StringDepository++;
1043 BootOptionStrDepository = StringDepository++;
1044 BootOptionHelpStrDepository = StringDepository++;
1045 DriverOptionStrDepository = StringDepository++;
1046 DriverOptionHelpStrDepository = StringDepository++;
1047 TerminalStrDepository = StringDepository;
1048 }
1049
1050 STRING_REF
1051 GetStringTokenFromDepository (
1052 IN BMM_CALLBACK_DATA *CallbackData,
1053 IN STRING_DEPOSITORY *StringDepository
1054 )
1055 /*++
1056 Routine Description:
1057 Fetch a usable string node from the string depository and return the string token.
1058
1059 Arguments:
1060 StringDepository - Pointer of the string depository.
1061
1062 Returns:
1063 STRING_REF - String token.
1064 --*/
1065 {
1066 STRING_LIST_NODE *CurrentListNode;
1067 STRING_LIST_NODE *NextListNode;
1068
1069 CurrentListNode = StringDepository->CurrentNode;
1070
1071 if ((NULL != CurrentListNode) && (NULL != CurrentListNode->Next)) {
1072 //
1073 // Fetch one reclaimed node from the list.
1074 //
1075 NextListNode = StringDepository->CurrentNode->Next;
1076 } else {
1077 //
1078 // If there is no usable node in the list, update the list.
1079 //
1080 NextListNode = AllocateZeroPool (sizeof (STRING_LIST_NODE));
1081
1082 CallbackData->Hii->NewString (
1083 CallbackData->Hii,
1084 NULL,
1085 CallbackData->BmmHiiHandle,
1086 &(NextListNode->StringToken),
1087 L" "
1088 );
1089
1090 ASSERT (NextListNode->StringToken != 0);
1091
1092 StringDepository->TotalNodeNumber++;
1093
1094 if (NULL == CurrentListNode) {
1095 StringDepository->ListHead = NextListNode;
1096 } else {
1097 CurrentListNode->Next = NextListNode;
1098 }
1099 }
1100
1101 StringDepository->CurrentNode = NextListNode;
1102
1103 return StringDepository->CurrentNode->StringToken;
1104 }
1105
1106 VOID
1107 ReclaimStringDepository (
1108 VOID
1109 )
1110 /*++
1111 Routine Description:
1112 Reclaim string depositories by moving the current node pointer to list head..
1113
1114 Arguments:
1115 None.
1116
1117 Returns:
1118 None.
1119 --*/
1120 {
1121 UINTN DepositoryIndex;
1122 STRING_DEPOSITORY *StringDepository;
1123
1124 StringDepository = FileOptionStrDepository;
1125 for (DepositoryIndex = 0; DepositoryIndex < STRING_DEPOSITORY_NUMBER; DepositoryIndex++) {
1126 StringDepository->CurrentNode = StringDepository->ListHead;
1127 StringDepository++;
1128 }
1129 }
1130
1131 VOID
1132 CleanUpStringDepository (
1133 VOID
1134 )
1135 /*++
1136 Routine Description:
1137 Release resource for all the string depositories.
1138
1139 Arguments:
1140 None.
1141
1142 Returns:
1143 None.
1144 --*/
1145 {
1146 UINTN NodeIndex;
1147 UINTN DepositoryIndex;
1148 STRING_LIST_NODE *CurrentListNode;
1149 STRING_LIST_NODE *NextListNode;
1150 STRING_DEPOSITORY *StringDepository;
1151
1152 //
1153 // Release string list nodes.
1154 //
1155 StringDepository = FileOptionStrDepository;
1156 for (DepositoryIndex = 0; DepositoryIndex < STRING_DEPOSITORY_NUMBER; DepositoryIndex++) {
1157 CurrentListNode = StringDepository->ListHead;
1158 for (NodeIndex = 0; NodeIndex < StringDepository->TotalNodeNumber; NodeIndex++) {
1159 NextListNode = CurrentListNode->Next;
1160 SafeFreePool (CurrentListNode);
1161 CurrentListNode = NextListNode;
1162 }
1163
1164 StringDepository++;
1165 }
1166 //
1167 // Release string depository.
1168 //
1169 SafeFreePool (FileOptionStrDepository);
1170 }
1171
1172 EFI_STATUS
1173 BdsStartBootMaint (
1174 VOID
1175 )
1176 /*++
1177
1178 Routine Description:
1179 Start boot maintenance manager
1180
1181 Arguments:
1182
1183 Returns:
1184
1185 --*/
1186 {
1187 EFI_STATUS Status;
1188 LIST_ENTRY BdsBootOptionList;
1189
1190 InitializeListHead (&BdsBootOptionList);
1191
1192 //
1193 // Connect all prior to entering the platform setup menu.
1194 //
1195 if (!gConnectAllHappened) {
1196 BdsLibConnectAllDriversToAllControllers ();
1197 gConnectAllHappened = TRUE;
1198 }
1199 //
1200 // Have chance to enumerate boot device
1201 //
1202 BdsLibEnumerateAllBootOption (&BdsBootOptionList);
1203
1204 //
1205 // Init the BMM
1206 //
1207 Status = InitializeBM ();
1208
1209 return Status;
1210 }
1211
1212 EFI_STATUS
1213 FormSetDispatcher (
1214 IN BMM_CALLBACK_DATA *CallbackData
1215 )
1216 /*++
1217
1218 Routine Description:
1219 Dispatch BMM formset and FileExplorer formset.
1220
1221 Arguments:
1222
1223 Returns:
1224
1225 --*/
1226 {
1227 EFI_FORM_BROWSER_PROTOCOL *FormConfig;
1228 UINT8 *Location;
1229 EFI_STATUS Status;
1230 UINTN Index;
1231 BM_MENU_ENTRY *NewMenuEntry;
1232 BM_FILE_CONTEXT *NewFileContext;
1233 BOOLEAN BootMaintMenuResetRequired;
1234
1235 Location = NULL;
1236 Index = 0;
1237 NewMenuEntry = NULL;
1238 NewFileContext = NULL;
1239
1240 //
1241 // There should only be one Form Configuration protocol
1242 //
1243 Status = EfiLibLocateProtocol (&gEfiFormBrowserProtocolGuid, &FormConfig);
1244 if (EFI_ERROR (Status)) {
1245 return Status;
1246 }
1247
1248 while (1) {
1249 UpdatePageId (CallbackData, FORM_MAIN_ID);
1250
1251 BootMaintMenuResetRequired = FALSE;
1252 Status = FormConfig->SendForm (
1253 FormConfig,
1254 TRUE,
1255 &(CallbackData->BmmHiiHandle),
1256 1,
1257 NULL,
1258 NULL,
1259 (UINT8 *) CallbackData->BmmFakeNvData,
1260 NULL,
1261 &BootMaintMenuResetRequired
1262 );
1263
1264 if (BootMaintMenuResetRequired) {
1265 EnableResetRequired ();
1266 }
1267
1268 ReclaimStringDepository ();
1269
1270 //
1271 // When this Formset returns, check if we are going to explore files.
1272 //
1273 if (INACTIVE_STATE != CallbackData->FeCurrentState) {
1274 UpdateFileExplorer (CallbackData, 0);
1275
1276 BootMaintMenuResetRequired = FALSE;
1277 Status = FormConfig->SendForm (
1278 FormConfig,
1279 TRUE,
1280 &(CallbackData->FeHiiHandle),
1281 1,
1282 NULL,
1283 NULL,
1284 NULL,
1285 NULL,
1286 &BootMaintMenuResetRequired
1287 );
1288
1289 if (BootMaintMenuResetRequired) {
1290 EnableResetRequired ();
1291 }
1292
1293 CallbackData->FeCurrentState = INACTIVE_STATE;
1294 CallbackData->FeDisplayContext = UNKNOWN_CONTEXT;
1295 ReclaimStringDepository ();
1296 } else {
1297 break;
1298 }
1299 }
1300
1301 return Status;
1302 }
1303
1304 VOID
1305 CreateCallbackPacket (
1306 OUT EFI_HII_CALLBACK_PACKET **Packet,
1307 IN UINT16 Flags
1308 )
1309 {
1310 *Packet = (EFI_HII_CALLBACK_PACKET *) AllocateZeroPool (sizeof (EFI_HII_CALLBACK_PACKET) + 2);
1311 ASSERT (*Packet != NULL);
1312
1313 (*Packet)->DataArray.EntryCount = 1;
1314 (*Packet)->DataArray.NvRamMap = NULL;
1315 ((EFI_IFR_DATA_ENTRY *) (&((*Packet)->DataArray) + 1))->Flags = Flags;
1316 }