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