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