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