]> git.proxmox.com Git - mirror_edk2.git/blob - MdeModulePkg/Library/BootMaintenanceManagerUiLib/BootOption.c
8680a51d78c75cb4798632d828c733dc5f0b5d42
[mirror_edk2.git] / MdeModulePkg / Library / BootMaintenanceManagerUiLib / BootOption.c
1 /** @file
2 Provide boot option support for Application "BootMaint"
3
4 Include file system navigation, system handle selection
5
6 Boot option manipulation
7
8 Copyright (c) 2004 - 2016, Intel Corporation. All rights reserved.<BR>
9 This program and the accompanying materials
10 are licensed and made available under the terms and conditions of the BSD License
11 which accompanies this distribution. The full text of the license may be found at
12 http://opensource.org/licenses/bsd-license.php
13
14 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
15 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
16
17 **/
18
19 #include "BootMaintenanceManager.h"
20
21 ///
22 /// Define the maximum characters that will be accepted.
23 ///
24 #define MAX_CHAR 480
25
26 /**
27
28 Check whether a reset is needed, if reset is needed, Popup a menu to notice user.
29
30 **/
31 VOID
32 BmmSetupResetReminder (
33 VOID
34 )
35 {
36 EFI_INPUT_KEY Key;
37 CHAR16 *StringBuffer1;
38 CHAR16 *StringBuffer2;
39 EFI_STATUS Status;
40 EDKII_FORM_BROWSER_EXTENSION2_PROTOCOL *FormBrowserEx2;
41
42 //
43 // Use BrowserEx2 protocol to check whether reset is required.
44 //
45 Status = gBS->LocateProtocol (&gEdkiiFormBrowserEx2ProtocolGuid, NULL, (VOID **) &FormBrowserEx2);
46
47 //
48 //check any reset required change is applied? if yes, reset system
49 //
50 if (!EFI_ERROR(Status) && FormBrowserEx2->IsResetRequired()) {
51 StringBuffer1 = AllocateZeroPool (MAX_CHAR * sizeof (CHAR16));
52 ASSERT (StringBuffer1 != NULL);
53 StringBuffer2 = AllocateZeroPool (MAX_CHAR * sizeof (CHAR16));
54 ASSERT (StringBuffer2 != NULL);
55 StrCpyS (StringBuffer1, MAX_CHAR, L"Configuration changed. Reset to apply it Now.");
56 StrCpyS (StringBuffer2, MAX_CHAR, L"Press ENTER to reset");
57 //
58 // Popup a menu to notice user
59 //
60 do {
61 CreatePopUp (EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE, &Key, StringBuffer1, StringBuffer2, NULL);
62 } while (Key.UnicodeChar != CHAR_CARRIAGE_RETURN);
63
64 FreePool (StringBuffer1);
65 FreePool (StringBuffer2);
66
67 gRT->ResetSystem (EfiResetCold, EFI_SUCCESS, 0, NULL);
68 }
69 }
70
71 /**
72 Create a menu entry by given menu type.
73
74 @param MenuType The Menu type to be created.
75
76 @retval NULL If failed to create the menu.
77 @return the new menu entry.
78
79 **/
80 BM_MENU_ENTRY *
81 BOpt_CreateMenuEntry (
82 UINTN MenuType
83 )
84 {
85 BM_MENU_ENTRY *MenuEntry;
86 UINTN ContextSize;
87
88 //
89 // Get context size according to menu type
90 //
91 switch (MenuType) {
92 case BM_LOAD_CONTEXT_SELECT:
93 ContextSize = sizeof (BM_LOAD_CONTEXT);
94 break;
95
96 case BM_FILE_CONTEXT_SELECT:
97 ContextSize = sizeof (BM_FILE_CONTEXT);
98 break;
99
100 case BM_CONSOLE_CONTEXT_SELECT:
101 ContextSize = sizeof (BM_CONSOLE_CONTEXT);
102 break;
103
104 case BM_TERMINAL_CONTEXT_SELECT:
105 ContextSize = sizeof (BM_TERMINAL_CONTEXT);
106 break;
107
108 case BM_HANDLE_CONTEXT_SELECT:
109 ContextSize = sizeof (BM_HANDLE_CONTEXT);
110 break;
111
112 default:
113 ContextSize = 0;
114 break;
115 }
116
117 if (ContextSize == 0) {
118 return NULL;
119 }
120
121 //
122 // Create new menu entry
123 //
124 MenuEntry = AllocateZeroPool (sizeof (BM_MENU_ENTRY));
125 if (MenuEntry == NULL) {
126 return NULL;
127 }
128
129 MenuEntry->VariableContext = AllocateZeroPool (ContextSize);
130 if (MenuEntry->VariableContext == NULL) {
131 FreePool (MenuEntry);
132 return NULL;
133 }
134
135 MenuEntry->Signature = BM_MENU_ENTRY_SIGNATURE;
136 MenuEntry->ContextSelection = MenuType;
137 return MenuEntry;
138 }
139
140 /**
141 Free up all resource allocated for a BM_MENU_ENTRY.
142
143 @param MenuEntry A pointer to BM_MENU_ENTRY.
144
145 **/
146 VOID
147 BOpt_DestroyMenuEntry (
148 BM_MENU_ENTRY *MenuEntry
149 )
150 {
151 BM_LOAD_CONTEXT *LoadContext;
152 BM_FILE_CONTEXT *FileContext;
153 BM_CONSOLE_CONTEXT *ConsoleContext;
154 BM_TERMINAL_CONTEXT *TerminalContext;
155 BM_HANDLE_CONTEXT *HandleContext;
156
157 //
158 // Select by the type in Menu entry for current context type
159 //
160 switch (MenuEntry->ContextSelection) {
161 case BM_LOAD_CONTEXT_SELECT:
162 LoadContext = (BM_LOAD_CONTEXT *) MenuEntry->VariableContext;
163 FreePool (LoadContext->FilePathList);
164 if (LoadContext->OptionalData != NULL) {
165 FreePool (LoadContext->OptionalData);
166 }
167 FreePool (LoadContext);
168 break;
169
170 case BM_FILE_CONTEXT_SELECT:
171 FileContext = (BM_FILE_CONTEXT *) MenuEntry->VariableContext;
172
173 if (!FileContext->IsRoot) {
174 FreePool (FileContext->DevicePath);
175 } else {
176 if (FileContext->FHandle != NULL) {
177 FileContext->FHandle->Close (FileContext->FHandle);
178 }
179 }
180
181 if (FileContext->FileName != NULL) {
182 FreePool (FileContext->FileName);
183 }
184 if (FileContext->Info != NULL) {
185 FreePool (FileContext->Info);
186 }
187 FreePool (FileContext);
188 break;
189
190 case BM_CONSOLE_CONTEXT_SELECT:
191 ConsoleContext = (BM_CONSOLE_CONTEXT *) MenuEntry->VariableContext;
192 FreePool (ConsoleContext->DevicePath);
193 FreePool (ConsoleContext);
194 break;
195
196 case BM_TERMINAL_CONTEXT_SELECT:
197 TerminalContext = (BM_TERMINAL_CONTEXT *) MenuEntry->VariableContext;
198 FreePool (TerminalContext->DevicePath);
199 FreePool (TerminalContext);
200 break;
201
202 case BM_HANDLE_CONTEXT_SELECT:
203 HandleContext = (BM_HANDLE_CONTEXT *) MenuEntry->VariableContext;
204 FreePool (HandleContext);
205 break;
206
207 default:
208 break;
209 }
210
211 FreePool (MenuEntry->DisplayString);
212 if (MenuEntry->HelpString != NULL) {
213 FreePool (MenuEntry->HelpString);
214 }
215
216 FreePool (MenuEntry);
217 }
218
219 /**
220 Get the Menu Entry from the list in Menu Entry List.
221
222 If MenuNumber is great or equal to the number of Menu
223 Entry in the list, then ASSERT.
224
225 @param MenuOption The Menu Entry List to read the menu entry.
226 @param MenuNumber The index of Menu Entry.
227
228 @return The Menu Entry.
229
230 **/
231 BM_MENU_ENTRY *
232 BOpt_GetMenuEntry (
233 BM_MENU_OPTION *MenuOption,
234 UINTN MenuNumber
235 )
236 {
237 BM_MENU_ENTRY *NewMenuEntry;
238 UINTN Index;
239 LIST_ENTRY *List;
240
241 ASSERT (MenuNumber < MenuOption->MenuNumber);
242
243 List = MenuOption->Head.ForwardLink;
244 for (Index = 0; Index < MenuNumber; Index++) {
245 List = List->ForwardLink;
246 }
247
248 NewMenuEntry = CR (List, BM_MENU_ENTRY, Link, BM_MENU_ENTRY_SIGNATURE);
249
250 return NewMenuEntry;
251 }
252
253 /**
254 Free resources allocated in Allocate Rountine.
255
256 @param FreeMenu Menu to be freed
257 **/
258 VOID
259 BOpt_FreeMenu (
260 BM_MENU_OPTION *FreeMenu
261 )
262 {
263 BM_MENU_ENTRY *MenuEntry;
264 while (!IsListEmpty (&FreeMenu->Head)) {
265 MenuEntry = CR (
266 FreeMenu->Head.ForwardLink,
267 BM_MENU_ENTRY,
268 Link,
269 BM_MENU_ENTRY_SIGNATURE
270 );
271 RemoveEntryList (&MenuEntry->Link);
272 BOpt_DestroyMenuEntry (MenuEntry);
273 }
274 FreeMenu->MenuNumber = 0;
275 }
276
277 /**
278
279 Build the BootOptionMenu according to BootOrder Variable.
280 This Routine will access the Boot#### to get EFI_LOAD_OPTION.
281
282 @param CallbackData The BMM context data.
283
284 @return EFI_NOT_FOUND Fail to find "BootOrder" variable.
285 @return EFI_SUCESS Success build boot option menu.
286
287 **/
288 EFI_STATUS
289 BOpt_GetBootOptions (
290 IN BMM_CALLBACK_DATA *CallbackData
291 )
292 {
293 UINTN Index;
294 UINT16 BootString[10];
295 UINT8 *LoadOptionFromVar;
296 UINTN BootOptionSize;
297 BOOLEAN BootNextFlag;
298 UINT16 *BootOrderList;
299 UINTN BootOrderListSize;
300 UINT16 *BootNext;
301 UINTN BootNextSize;
302 BM_MENU_ENTRY *NewMenuEntry;
303 BM_LOAD_CONTEXT *NewLoadContext;
304 UINT8 *LoadOptionPtr;
305 UINTN StringSize;
306 UINTN OptionalDataSize;
307 UINT8 *LoadOptionEnd;
308 EFI_DEVICE_PATH_PROTOCOL *DevicePath;
309 UINTN MenuCount;
310 UINT8 *Ptr;
311 EFI_BOOT_MANAGER_LOAD_OPTION *BootOption;
312 UINTN BootOptionCount;
313
314 MenuCount = 0;
315 BootOrderListSize = 0;
316 BootNextSize = 0;
317 BootOrderList = NULL;
318 BootNext = NULL;
319 LoadOptionFromVar = NULL;
320 BOpt_FreeMenu (&BootOptionMenu);
321 InitializeListHead (&BootOptionMenu.Head);
322
323 //
324 // Get the BootOrder from the Var
325 //
326 GetEfiGlobalVariable2 (L"BootOrder", (VOID **) &BootOrderList, &BootOrderListSize);
327 if (BootOrderList == NULL) {
328 return EFI_NOT_FOUND;
329 }
330
331 //
332 // Get the BootNext from the Var
333 //
334 GetEfiGlobalVariable2 (L"BootNext", (VOID **) &BootNext, &BootNextSize);
335 if (BootNext != NULL) {
336 if (BootNextSize != sizeof (UINT16)) {
337 FreePool (BootNext);
338 BootNext = NULL;
339 }
340 }
341 BootOption = EfiBootManagerGetLoadOptions (&BootOptionCount, LoadOptionTypeBoot);
342 for (Index = 0; Index < BootOrderListSize / sizeof (UINT16); Index++) {
343 //
344 // Don't display the hidden/inactive boot option
345 //
346 if (((BootOption[Index].Attributes & LOAD_OPTION_HIDDEN) != 0) || ((BootOption[Index].Attributes & LOAD_OPTION_ACTIVE) == 0)) {
347 continue;
348 }
349
350 UnicodeSPrint (BootString, sizeof (BootString), L"Boot%04x", BootOrderList[Index]);
351 //
352 // Get all loadoptions from the VAR
353 //
354 GetEfiGlobalVariable2 (BootString, (VOID **) &LoadOptionFromVar, &BootOptionSize);
355 if (LoadOptionFromVar == NULL) {
356 continue;
357 }
358
359 if (BootNext != NULL) {
360 BootNextFlag = (BOOLEAN) (*BootNext == BootOrderList[Index]);
361 } else {
362 BootNextFlag = FALSE;
363 }
364
365 NewMenuEntry = BOpt_CreateMenuEntry (BM_LOAD_CONTEXT_SELECT);
366 ASSERT (NULL != NewMenuEntry);
367
368 NewLoadContext = (BM_LOAD_CONTEXT *) NewMenuEntry->VariableContext;
369
370 LoadOptionPtr = LoadOptionFromVar;
371 LoadOptionEnd = LoadOptionFromVar + BootOptionSize;
372
373 NewMenuEntry->OptionNumber = BootOrderList[Index];
374 NewLoadContext->Deleted = FALSE;
375 NewLoadContext->IsBootNext = BootNextFlag;
376
377 //
378 // Is a Legacy Device?
379 //
380 Ptr = (UINT8 *) LoadOptionFromVar;
381
382 //
383 // Attribute = *(UINT32 *)Ptr;
384 //
385 Ptr += sizeof (UINT32);
386
387 //
388 // FilePathSize = *(UINT16 *)Ptr;
389 //
390 Ptr += sizeof (UINT16);
391
392 //
393 // Description = (CHAR16 *)Ptr;
394 //
395 Ptr += StrSize ((CHAR16 *) Ptr);
396
397 //
398 // Now Ptr point to Device Path
399 //
400 DevicePath = (EFI_DEVICE_PATH_PROTOCOL *) Ptr;
401 if ((BBS_DEVICE_PATH == DevicePath->Type) && (BBS_BBS_DP == DevicePath->SubType)) {
402 NewLoadContext->IsLegacy = TRUE;
403 } else {
404 NewLoadContext->IsLegacy = FALSE;
405 }
406 //
407 // LoadOption is a pointer type of UINT8
408 // for easy use with following LOAD_OPTION
409 // embedded in this struct
410 //
411
412 NewLoadContext->Attributes = *(UINT32 *) LoadOptionPtr;
413
414 LoadOptionPtr += sizeof (UINT32);
415
416 NewLoadContext->FilePathListLength = *(UINT16 *) LoadOptionPtr;
417 LoadOptionPtr += sizeof (UINT16);
418
419 StringSize = StrSize((UINT16*)LoadOptionPtr);
420
421 NewLoadContext->Description = AllocateZeroPool (StrSize((UINT16*)LoadOptionPtr));
422 ASSERT (NewLoadContext->Description != NULL);
423 StrCpyS (NewLoadContext->Description, StrSize((UINT16*)LoadOptionPtr) / sizeof (UINT16), (UINT16*)LoadOptionPtr);
424
425 ASSERT (NewLoadContext->Description != NULL);
426 NewMenuEntry->DisplayString = NewLoadContext->Description;
427 NewMenuEntry->DisplayStringToken = HiiSetString (CallbackData->BmmHiiHandle, 0, NewMenuEntry->DisplayString, NULL);
428
429 LoadOptionPtr += StringSize;
430
431 NewLoadContext->FilePathList = AllocateZeroPool (NewLoadContext->FilePathListLength);
432 ASSERT (NewLoadContext->FilePathList != NULL);
433 CopyMem (
434 NewLoadContext->FilePathList,
435 (EFI_DEVICE_PATH_PROTOCOL *) LoadOptionPtr,
436 NewLoadContext->FilePathListLength
437 );
438
439 NewMenuEntry->HelpString = UiDevicePathToStr (NewLoadContext->FilePathList);
440 NewMenuEntry->HelpStringToken = HiiSetString (CallbackData->BmmHiiHandle, 0, NewMenuEntry->HelpString, NULL);
441
442 LoadOptionPtr += NewLoadContext->FilePathListLength;
443
444 if (LoadOptionPtr < LoadOptionEnd) {
445 OptionalDataSize = BootOptionSize -
446 sizeof (UINT32) -
447 sizeof (UINT16) -
448 StringSize -
449 NewLoadContext->FilePathListLength;
450
451 NewLoadContext->OptionalData = AllocateZeroPool (OptionalDataSize);
452 ASSERT (NewLoadContext->OptionalData != NULL);
453 CopyMem (
454 NewLoadContext->OptionalData,
455 LoadOptionPtr,
456 OptionalDataSize
457 );
458 }
459
460 InsertTailList (&BootOptionMenu.Head, &NewMenuEntry->Link);
461 MenuCount++;
462 FreePool (LoadOptionFromVar);
463 }
464 EfiBootManagerFreeLoadOptions (BootOption, BootOptionCount);
465
466 if (BootNext != NULL) {
467 FreePool (BootNext);
468 }
469 if (BootOrderList != NULL) {
470 FreePool (BootOrderList);
471 }
472
473 BootOptionMenu.MenuNumber = MenuCount;
474 return EFI_SUCCESS;
475 }
476
477 /**
478
479 Find drivers that will be added as Driver#### variables from handles
480 in current system environment
481 All valid handles in the system except those consume SimpleFs, LoadFile
482 are stored in DriverMenu for future use.
483
484 @retval EFI_SUCCESS The function complets successfully.
485 @return Other value if failed to build the DriverMenu.
486
487 **/
488 EFI_STATUS
489 BOpt_FindDrivers (
490 VOID
491 )
492 {
493 UINTN NoDevicePathHandles;
494 EFI_HANDLE *DevicePathHandle;
495 UINTN Index;
496 EFI_STATUS Status;
497 BM_MENU_ENTRY *NewMenuEntry;
498 BM_HANDLE_CONTEXT *NewHandleContext;
499 EFI_HANDLE CurHandle;
500 UINTN OptionNumber;
501 EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *SimpleFs;
502 EFI_LOAD_FILE_PROTOCOL *LoadFile;
503
504 SimpleFs = NULL;
505 LoadFile = NULL;
506
507 InitializeListHead (&DriverMenu.Head);
508
509 //
510 // At first, get all handles that support Device Path
511 // protocol which is the basic requirement for
512 // Driver####
513 //
514 Status = gBS->LocateHandleBuffer (
515 ByProtocol,
516 &gEfiDevicePathProtocolGuid,
517 NULL,
518 &NoDevicePathHandles,
519 &DevicePathHandle
520 );
521 if (EFI_ERROR (Status)) {
522 return Status;
523 }
524
525 OptionNumber = 0;
526 for (Index = 0; Index < NoDevicePathHandles; Index++) {
527 CurHandle = DevicePathHandle[Index];
528
529 Status = gBS->HandleProtocol (
530 CurHandle,
531 &gEfiSimpleFileSystemProtocolGuid,
532 (VOID **) &SimpleFs
533 );
534 if (Status == EFI_SUCCESS) {
535 continue;
536 }
537
538 Status = gBS->HandleProtocol (
539 CurHandle,
540 &gEfiLoadFileProtocolGuid,
541 (VOID **) &LoadFile
542 );
543 if (Status == EFI_SUCCESS) {
544 continue;
545 }
546
547 NewMenuEntry = BOpt_CreateMenuEntry (BM_HANDLE_CONTEXT_SELECT);
548 if (NULL == NewMenuEntry) {
549 FreePool (DevicePathHandle);
550 return EFI_OUT_OF_RESOURCES;
551 }
552
553 NewHandleContext = (BM_HANDLE_CONTEXT *) NewMenuEntry->VariableContext;
554 NewHandleContext->Handle = CurHandle;
555 NewHandleContext->DevicePath = DevicePathFromHandle (CurHandle);
556 NewMenuEntry->DisplayString = UiDevicePathToStr (NewHandleContext->DevicePath);
557 NewMenuEntry->DisplayStringToken = HiiSetString (mBmmCallbackInfo->BmmHiiHandle,0,NewMenuEntry->DisplayString,NULL);
558 NewMenuEntry->HelpString = NULL;
559 NewMenuEntry->HelpStringToken = NewMenuEntry->DisplayStringToken;
560 NewMenuEntry->OptionNumber = OptionNumber;
561 OptionNumber++;
562 InsertTailList (&DriverMenu.Head, &NewMenuEntry->Link);
563
564 }
565
566 if (DevicePathHandle != NULL) {
567 FreePool (DevicePathHandle);
568 }
569
570 DriverMenu.MenuNumber = OptionNumber;
571 return EFI_SUCCESS;
572 }
573
574 /**
575
576 Get the Option Number that has not been allocated for use.
577
578 @param Type The type of Option.
579
580 @return The available Option Number.
581
582 **/
583 UINT16
584 BOpt_GetOptionNumber (
585 CHAR16 *Type
586 )
587 {
588 UINT16 *OrderList;
589 UINTN OrderListSize;
590 UINTN Index;
591 CHAR16 StrTemp[20];
592 UINT16 *OptionBuffer;
593 UINT16 OptionNumber;
594 UINTN OptionSize;
595
596 OrderListSize = 0;
597 OrderList = NULL;
598 OptionNumber = 0;
599 Index = 0;
600
601 UnicodeSPrint (StrTemp, sizeof (StrTemp), L"%sOrder", Type);
602
603 GetEfiGlobalVariable2 (StrTemp, (VOID **) &OrderList, &OrderListSize);
604 for (OptionNumber = 0; ; OptionNumber++) {
605 if (OrderList != NULL) {
606 for (Index = 0; Index < OrderListSize / sizeof (UINT16); Index++) {
607 if (OptionNumber == OrderList[Index]) {
608 break;
609 }
610 }
611 }
612
613 if (Index < OrderListSize / sizeof (UINT16)) {
614 //
615 // The OptionNumber occurs in the OrderList, continue to use next one
616 //
617 continue;
618 }
619 UnicodeSPrint (StrTemp, sizeof (StrTemp), L"%s%04x", Type, (UINTN) OptionNumber);
620 DEBUG((EFI_D_ERROR,"Option = %s\n", StrTemp));
621 GetEfiGlobalVariable2 (StrTemp, (VOID **) &OptionBuffer, &OptionSize);
622 if (NULL == OptionBuffer) {
623 //
624 // The Boot[OptionNumber] / Driver[OptionNumber] NOT occurs, we found it
625 //
626 break;
627 }
628 }
629
630 return OptionNumber;
631 }
632
633 /**
634
635 Get the Option Number for Boot#### that does not used.
636
637 @return The available Option Number.
638
639 **/
640 UINT16
641 BOpt_GetBootOptionNumber (
642 VOID
643 )
644 {
645 return BOpt_GetOptionNumber (L"Boot");
646 }
647
648 /**
649
650 Get the Option Number for Driver#### that does not used.
651
652 @return The unused Option Number.
653
654 **/
655 UINT16
656 BOpt_GetDriverOptionNumber (
657 VOID
658 )
659 {
660 return BOpt_GetOptionNumber (L"Driver");
661 }
662
663 /**
664
665 Build up all DriverOptionMenu
666
667 @param CallbackData The BMM context data.
668
669 @retval EFI_SUCESS The functin completes successfully.
670 @retval EFI_OUT_OF_RESOURCES Not enough memory to compete the operation.
671 @retval EFI_NOT_FOUND Fail to get "DriverOrder" variable.
672
673 **/
674 EFI_STATUS
675 BOpt_GetDriverOptions (
676 IN BMM_CALLBACK_DATA *CallbackData
677 )
678 {
679 UINTN Index;
680 UINT16 DriverString[12];
681 UINT8 *LoadOptionFromVar;
682 UINTN DriverOptionSize;
683
684 UINT16 *DriverOrderList;
685 UINTN DriverOrderListSize;
686 BM_MENU_ENTRY *NewMenuEntry;
687 BM_LOAD_CONTEXT *NewLoadContext;
688 UINT8 *LoadOptionPtr;
689 UINTN StringSize;
690 UINTN OptionalDataSize;
691 UINT8 *LoadOptionEnd;
692
693 DriverOrderListSize = 0;
694 DriverOrderList = NULL;
695 DriverOptionSize = 0;
696 LoadOptionFromVar = NULL;
697 BOpt_FreeMenu (&DriverOptionMenu);
698 InitializeListHead (&DriverOptionMenu.Head);
699 //
700 // Get the DriverOrder from the Var
701 //
702 GetEfiGlobalVariable2 (L"DriverOrder", (VOID **) &DriverOrderList, &DriverOrderListSize);
703 if (DriverOrderList == NULL) {
704 return EFI_NOT_FOUND;
705 }
706
707 for (Index = 0; Index < DriverOrderListSize / sizeof (UINT16); Index++) {
708 UnicodeSPrint (
709 DriverString,
710 sizeof (DriverString),
711 L"Driver%04x",
712 DriverOrderList[Index]
713 );
714 //
715 // Get all loadoptions from the VAR
716 //
717 GetEfiGlobalVariable2 (DriverString, (VOID **) &LoadOptionFromVar, &DriverOptionSize);
718 if (LoadOptionFromVar == NULL) {
719 continue;
720 }
721
722
723 NewMenuEntry = BOpt_CreateMenuEntry (BM_LOAD_CONTEXT_SELECT);
724 if (NULL == NewMenuEntry) {
725 return EFI_OUT_OF_RESOURCES;
726 }
727
728 NewLoadContext = (BM_LOAD_CONTEXT *) NewMenuEntry->VariableContext;
729 LoadOptionPtr = LoadOptionFromVar;
730 LoadOptionEnd = LoadOptionFromVar + DriverOptionSize;
731 NewMenuEntry->OptionNumber = DriverOrderList[Index];
732 NewLoadContext->Deleted = FALSE;
733 NewLoadContext->IsLegacy = FALSE;
734
735 //
736 // LoadOption is a pointer type of UINT8
737 // for easy use with following LOAD_OPTION
738 // embedded in this struct
739 //
740
741 NewLoadContext->Attributes = *(UINT32 *) LoadOptionPtr;
742
743 LoadOptionPtr += sizeof (UINT32);
744
745 NewLoadContext->FilePathListLength = *(UINT16 *) LoadOptionPtr;
746 LoadOptionPtr += sizeof (UINT16);
747
748 StringSize = StrSize ((UINT16 *) LoadOptionPtr);
749 NewLoadContext->Description = AllocateZeroPool (StringSize);
750 ASSERT (NewLoadContext->Description != NULL);
751 CopyMem (
752 NewLoadContext->Description,
753 (UINT16 *) LoadOptionPtr,
754 StringSize
755 );
756 NewMenuEntry->DisplayString = NewLoadContext->Description;
757 NewMenuEntry->DisplayStringToken = HiiSetString (CallbackData->BmmHiiHandle, 0, NewMenuEntry->DisplayString, NULL);
758
759 LoadOptionPtr += StringSize;
760
761 NewLoadContext->FilePathList = AllocateZeroPool (NewLoadContext->FilePathListLength);
762 ASSERT (NewLoadContext->FilePathList != NULL);
763 CopyMem (
764 NewLoadContext->FilePathList,
765 (EFI_DEVICE_PATH_PROTOCOL *) LoadOptionPtr,
766 NewLoadContext->FilePathListLength
767 );
768
769 NewMenuEntry->HelpString = UiDevicePathToStr (NewLoadContext->FilePathList);
770 NewMenuEntry->HelpStringToken = HiiSetString (CallbackData->BmmHiiHandle, 0, NewMenuEntry->HelpString, NULL);
771
772 LoadOptionPtr += NewLoadContext->FilePathListLength;
773
774 if (LoadOptionPtr < LoadOptionEnd) {
775 OptionalDataSize = DriverOptionSize -
776 sizeof (UINT32) -
777 sizeof (UINT16) -
778 StringSize -
779 NewLoadContext->FilePathListLength;
780
781 NewLoadContext->OptionalData = AllocateZeroPool (OptionalDataSize);
782 ASSERT (NewLoadContext->OptionalData != NULL);
783 CopyMem (
784 NewLoadContext->OptionalData,
785 LoadOptionPtr,
786 OptionalDataSize
787 );
788
789 }
790
791 InsertTailList (&DriverOptionMenu.Head, &NewMenuEntry->Link);
792 FreePool (LoadOptionFromVar);
793
794 }
795
796 if (DriverOrderList != NULL) {
797 FreePool (DriverOrderList);
798 }
799
800 DriverOptionMenu.MenuNumber = Index;
801 return EFI_SUCCESS;
802
803 }
804
805 /**
806 Get option number according to Boot#### and BootOrder variable.
807 The value is saved as #### + 1.
808
809 @param CallbackData The BMM context data.
810 **/
811 VOID
812 GetBootOrder (
813 IN BMM_CALLBACK_DATA *CallbackData
814 )
815 {
816 BMM_FAKE_NV_DATA *BmmConfig;
817 UINT16 Index;
818 UINT16 OptionOrderIndex;
819 UINTN DeviceType;
820 BM_MENU_ENTRY *NewMenuEntry;
821 BM_LOAD_CONTEXT *NewLoadContext;
822
823 ASSERT (CallbackData != NULL);
824
825 DeviceType = (UINTN) -1;
826 BmmConfig = &CallbackData->BmmFakeNvData;
827 ZeroMem (BmmConfig->BootOptionOrder, sizeof (BmmConfig->BootOptionOrder));
828
829 for (Index = 0, OptionOrderIndex = 0; ((Index < BootOptionMenu.MenuNumber) &&
830 (OptionOrderIndex < (sizeof (BmmConfig->BootOptionOrder) / sizeof (BmmConfig->BootOptionOrder[0]))));
831 Index++) {
832 NewMenuEntry = BOpt_GetMenuEntry (&BootOptionMenu, Index);
833 NewLoadContext = (BM_LOAD_CONTEXT *) NewMenuEntry->VariableContext;
834
835 if (NewLoadContext->IsLegacy) {
836 if (((BBS_BBS_DEVICE_PATH *) NewLoadContext->FilePathList)->DeviceType != DeviceType) {
837 DeviceType = ((BBS_BBS_DEVICE_PATH *) NewLoadContext->FilePathList)->DeviceType;
838 } else {
839 //
840 // Only show one legacy boot option for the same device type
841 // assuming the boot options are grouped by the device type
842 //
843 continue;
844 }
845 }
846 BmmConfig->BootOptionOrder[OptionOrderIndex++] = (UINT32) (NewMenuEntry->OptionNumber + 1);
847 }
848 }
849
850 /**
851 Get driver option order from globalc DriverOptionMenu.
852
853 @param CallbackData The BMM context data.
854
855 **/
856 VOID
857 GetDriverOrder (
858 IN BMM_CALLBACK_DATA *CallbackData
859 )
860 {
861 BMM_FAKE_NV_DATA *BmmConfig;
862 UINT16 Index;
863 UINT16 OptionOrderIndex;
864 UINTN DeviceType;
865 BM_MENU_ENTRY *NewMenuEntry;
866 BM_LOAD_CONTEXT *NewLoadContext;
867
868
869 ASSERT (CallbackData != NULL);
870
871 DeviceType = (UINTN) -1;
872 BmmConfig = &CallbackData->BmmFakeNvData;
873 ZeroMem (BmmConfig->DriverOptionOrder, sizeof (BmmConfig->DriverOptionOrder));
874
875 for (Index = 0, OptionOrderIndex = 0; ((Index < DriverOptionMenu.MenuNumber) &&
876 (OptionOrderIndex < (sizeof (BmmConfig->DriverOptionOrder) / sizeof (BmmConfig->DriverOptionOrder[0]))));
877 Index++) {
878 NewMenuEntry = BOpt_GetMenuEntry (&DriverOptionMenu, Index);
879 NewLoadContext = (BM_LOAD_CONTEXT *) NewMenuEntry->VariableContext;
880
881 if (NewLoadContext->IsLegacy) {
882 if (((BBS_BBS_DEVICE_PATH *) NewLoadContext->FilePathList)->DeviceType != DeviceType) {
883 DeviceType = ((BBS_BBS_DEVICE_PATH *) NewLoadContext->FilePathList)->DeviceType;
884 } else {
885 //
886 // Only show one legacy boot option for the same device type
887 // assuming the boot options are grouped by the device type
888 //
889 continue;
890 }
891 }
892 BmmConfig->DriverOptionOrder[OptionOrderIndex++] = (UINT32) (NewMenuEntry->OptionNumber + 1);
893 }
894 }
895
896 /**
897 Boot the file specified by the input file path info.
898
899 @param FilePath Point to the file path.
900
901 @retval TRUE Exit caller function.
902 @retval FALSE Not exit caller function.
903 **/
904 BOOLEAN
905 EFIAPI
906 BootFromFile (
907 IN EFI_DEVICE_PATH_PROTOCOL *FilePath
908 )
909 {
910 EFI_BOOT_MANAGER_LOAD_OPTION BootOption;
911 CHAR16 *FileName;
912
913 FileName = NULL;
914
915 FileName = ExtractFileNameFromDevicePath(FilePath);
916 if (FileName != NULL) {
917 EfiBootManagerInitializeLoadOption (
918 &BootOption,
919 0,
920 LoadOptionTypeBoot,
921 LOAD_OPTION_ACTIVE,
922 FileName,
923 FilePath,
924 NULL,
925 0
926 );
927 //
928 // Since current no boot from removable media directly is allowed */
929 //
930 gST->ConOut->ClearScreen (gST->ConOut);
931 //
932 // Check whether need to reset system.
933 //
934 BmmSetupResetReminder ();
935
936 BmmSetConsoleMode (FALSE);
937 EfiBootManagerBoot (&BootOption);
938 BmmSetConsoleMode (TRUE);
939
940 FreePool(FileName);
941
942 EfiBootManagerFreeLoadOption (&BootOption);
943 }
944
945 return FALSE;
946 }
947
948 /**
949 Display the form base on the selected file.
950
951 @param FilePath Point to the file path.
952 @param FormId The form need to display.
953
954 **/
955 BOOLEAN
956 ReSendForm(
957 IN EFI_DEVICE_PATH_PROTOCOL *FilePath,
958 IN EFI_FORM_ID FormId
959 )
960 {
961 gBootMaintenancePrivate.LoadContext->FilePathList = FilePath;
962
963 UpdateOptionPage(&gBootMaintenancePrivate, FormId, FilePath);
964
965 gBootMaintenancePrivate.FormBrowser2->SendForm (
966 gBootMaintenancePrivate.FormBrowser2,
967 &gBootMaintenancePrivate.BmmHiiHandle,
968 1,
969 &mBootMaintGuid,
970 FormId,
971 NULL,
972 NULL
973 );
974 return TRUE;
975 }
976
977 /**
978 Create boot option base on the input file path info.
979
980 @param FilePath Point to the file path.
981
982 @retval TRUE Exit caller function.
983 @retval FALSE Not exit caller function.
984 **/
985 BOOLEAN
986 EFIAPI
987 CreateBootOptionFromFile (
988 IN EFI_DEVICE_PATH_PROTOCOL *FilePath
989 )
990 {
991 return ReSendForm(FilePath, FORM_BOOT_ADD_ID);
992 }
993
994 /**
995 Create driver option base on the input file path info.
996
997 @param FilePath Point to the file path.
998
999 @retval TRUE Exit caller function.
1000 @retval FALSE Not exit caller function.
1001
1002 **/
1003 BOOLEAN
1004 EFIAPI
1005 CreateDriverOptionFromFile (
1006 IN EFI_DEVICE_PATH_PROTOCOL *FilePath
1007 )
1008 {
1009 return ReSendForm(FilePath, FORM_DRV_ADD_FILE_ID);
1010 }
1011