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