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