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