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