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