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