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